diff --git a/src/protocol/parser/pass_definitions.rs b/src/protocol/parser/pass_definitions.rs index 66ed638cc16da38f731d12225efd5d7c0a7da217..3b0d9abe5004eb827700c49d090cd32e560feba1 100644 --- a/src/protocol/parser/pass_definitions.rs +++ b/src/protocol/parser/pass_definitions.rs @@ -273,33 +273,18 @@ impl PassDefinitions { // Consume return types consume_token(&module.source, iter, TokenKind::ArrowRight)?; - let mut return_types = self.parser_types.start_section(); - let mut open_curly_pos = iter.last_valid_pos(); // bogus value - consume_comma_separated_until( - TokenKind::OpenCurly, &module.source, iter, ctx, - |source, iter, ctx| { - let poly_vars = ctx.heap[definition_id].poly_vars(); - self.type_parser.consume_parser_type( - iter, &ctx.heap, source, &ctx.symbols, poly_vars, definition_id, - module_scope, false, None - ) - }, - &mut return_types, "a return type", Some(&mut open_curly_pos) + let poly_vars = ctx.heap[definition_id].poly_vars(); + let parser_type = self.type_parser.consume_parser_type( + iter, &ctx.heap, &module.source, &ctx.symbols, poly_vars, definition_id, + module_scope, false, None )?; - let return_types = return_types.into_vec(); - - match return_types.len() { - 0 => return Err(ParseError::new_error_str_at_pos(&module.source, open_curly_pos, "expected a return type")), - 1 => {}, - _ => return Err(ParseError::new_error_str_at_pos(&module.source, open_curly_pos, "multiple return types are not (yet) allowed")), - } - // Consume block - let body = self.consume_block_statement_without_leading_curly(module, iter, ctx, open_curly_pos)?; + // Consume block and the definition's scope + let body = self.consume_block_statement(module, iter, ctx)?; // Assign everything in the preallocated AST node let function = ctx.heap[definition_id].as_function_mut(); - function.return_types = return_types; + function.return_type = parser_type; function.parameters = parameters; function.body = body; @@ -340,187 +325,136 @@ impl PassDefinitions { Ok(()) } - /// Consumes a block statement. If the resulting statement is not a block - /// (e.g. for a shorthand "if (expr) single_statement") then it will be - /// wrapped in one - fn consume_block_or_wrapped_statement( - &mut self, module: &Module, iter: &mut TokenIter, ctx: &mut PassCtx - ) -> Result { - if Some(TokenKind::OpenCurly) == iter.next() { - // This is a block statement - self.consume_block_statement(module, iter, ctx) - } else { - // Not a block statement, so wrap it in one - let mut statements = self.statements.start_section(); - let wrap_begin_pos = iter.last_valid_pos(); - self.consume_statement(module, iter, ctx, &mut statements)?; - let wrap_end_pos = iter.last_valid_pos(); - - let statements = statements.into_vec(); - - let id = ctx.heap.alloc_block_statement(|this| BlockStatement{ - this, - is_implicit: true, - span: InputSpan::from_positions(wrap_begin_pos, wrap_end_pos), - statements, - end_block: EndBlockStatementId::new_invalid(), - scope_node: ScopeNode::new_invalid(), - first_unique_id_in_scope: -1, - next_unique_id_in_scope: -1, - locals: Vec::new(), - labels: Vec::new(), - next: StatementId::new_invalid(), - }); - - let end_block = ctx.heap.alloc_end_block_statement(|this| EndBlockStatement{ - this, start_block: id, next: StatementId::new_invalid() - }); - - let block_stmt = &mut ctx.heap[id]; - block_stmt.end_block = end_block; - - Ok(id) - } - } - /// Consumes a statement and returns a boolean indicating whether it was a /// block or not. - fn consume_statement( - &mut self, module: &Module, iter: &mut TokenIter, ctx: &mut PassCtx, section: &mut ScopedSection - ) -> Result<(), ParseError> { + fn consume_statement(&mut self, module: &Module, iter: &mut TokenIter, ctx: &mut PassCtx) -> Result { let next = iter.next().expect("consume_statement has a next token"); if next == TokenKind::OpenCurly { let id = self.consume_block_statement(module, iter, ctx)?; - section.push(id.upcast()); + return Ok(id.upcast()); } else if next == TokenKind::Ident { let ident = peek_ident(&module.source, iter).unwrap(); if ident == KW_STMT_IF { // Consume if statement and place end-if statement directly // after it. let id = self.consume_if_statement(module, iter, ctx)?; - section.push(id.upcast()); let end_if = ctx.heap.alloc_end_if_statement(|this| EndIfStatement { this, start_if: id, next: StatementId::new_invalid() }); - section.push(end_if.upcast()); let if_stmt = &mut ctx.heap[id]; if_stmt.end_if = end_if; + + return Ok(id.upcast()); } else if ident == KW_STMT_WHILE { let id = self.consume_while_statement(module, iter, ctx)?; - section.push(id.upcast()); let end_while = ctx.heap.alloc_end_while_statement(|this| EndWhileStatement { this, start_while: id, next: StatementId::new_invalid() }); - section.push(end_while.upcast()); let while_stmt = &mut ctx.heap[id]; while_stmt.end_while = end_while; + + return Ok(id.upcast()); } else if ident == KW_STMT_BREAK { let id = self.consume_break_statement(module, iter, ctx)?; - section.push(id.upcast()); + return Ok(id.upcast()); } else if ident == KW_STMT_CONTINUE { let id = self.consume_continue_statement(module, iter, ctx)?; - section.push(id.upcast()); + return Ok(id.upcast()); } else if ident == KW_STMT_SYNC { let id = self.consume_synchronous_statement(module, iter, ctx)?; - section.push(id.upcast()); let end_sync = ctx.heap.alloc_end_synchronous_statement(|this| EndSynchronousStatement { this, start_sync: id, next: StatementId::new_invalid() }); - section.push(end_sync.upcast()); let sync_stmt = &mut ctx.heap[id]; sync_stmt.end_sync = end_sync; + + return Ok(id.upcast()); } else if ident == KW_STMT_FORK { let id = self.consume_fork_statement(module, iter, ctx)?; - section.push(id.upcast()); let end_fork = ctx.heap.alloc_end_fork_statement(|this| EndForkStatement { this, start_fork: id, next: StatementId::new_invalid(), }); - section.push(end_fork.upcast()); let fork_stmt = &mut ctx.heap[id]; fork_stmt.end_fork = end_fork; + + return Ok(id.upcast()); } else if ident == KW_STMT_SELECT { let id = self.consume_select_statement(module, iter, ctx)?; - section.push(id.upcast()); let end_select = ctx.heap.alloc_end_select_statement(|this| EndSelectStatement{ this, start_select: id, next: StatementId::new_invalid(), }); - section.push(end_select.upcast()); let select_stmt = &mut ctx.heap[id]; select_stmt.end_select = end_select; + + return Ok(id.upcast()); } else if ident == KW_STMT_RETURN { let id = self.consume_return_statement(module, iter, ctx)?; - section.push(id.upcast()); + return Ok(id.upcast()); } else if ident == KW_STMT_GOTO { let id = self.consume_goto_statement(module, iter, ctx)?; - section.push(id.upcast()); + return Ok(id.upcast()); } else if ident == KW_STMT_NEW { let id = self.consume_new_statement(module, iter, ctx)?; - section.push(id.upcast()); + return Ok(id.upcast()); } else if ident == KW_STMT_CHANNEL { let id = self.consume_channel_statement(module, iter, ctx)?; - section.push(id.upcast().upcast()); + return Ok(id.upcast().upcast()); } else if iter.peek() == Some(TokenKind::Colon) { - self.consume_labeled_statement(module, iter, ctx, section)?; + let id = self.consume_labeled_statement(module, iter, ctx)?; + return Ok(id.upcast()); } else { // Two fallback possibilities: the first one is a memory // declaration, the other one is to parse it as a normal // expression. This is a bit ugly. if let Some(memory_stmt_id) = self.maybe_consume_memory_statement_without_semicolon(module, iter, ctx)? { consume_token(&module.source, iter, TokenKind::SemiColon)?; - section.push(memory_stmt_id.upcast().upcast()); + return Ok(memory_stmt_id.upcast().upcast()); } else { let id = self.consume_expression_statement(module, iter, ctx)?; - section.push(id.upcast()); + return Ok(id.upcast()); } } } else if next == TokenKind::OpenParen { // Same as above: memory statement or normal expression if let Some(memory_stmt_id) = self.maybe_consume_memory_statement_without_semicolon(module, iter, ctx)? { consume_token(&module.source, iter, TokenKind::SemiColon)?; - section.push(memory_stmt_id.upcast().upcast()); + return Ok(memory_stmt_id.upcast().upcast()); } else { let id = self.consume_expression_statement(module, iter, ctx)?; - section.push(id.upcast()); + return Ok(id.upcast()); } } else { let id = self.consume_expression_statement(module, iter, ctx)?; - section.push(id.upcast()); + return Ok(id.upcast()); } - - return Ok(()); } fn consume_block_statement( &mut self, module: &Module, iter: &mut TokenIter, ctx: &mut PassCtx ) -> Result { - let open_span = consume_token(&module.source, iter, TokenKind::OpenCurly)?; - self.consume_block_statement_without_leading_curly(module, iter, ctx, open_span.begin) - } + let open_curly_span = consume_token(&module.source, iter, TokenKind::OpenCurly)?; - fn consume_block_statement_without_leading_curly( - &mut self, module: &Module, iter: &mut TokenIter, ctx: &mut PassCtx, open_curly_pos: InputPosition - ) -> Result { let mut stmt_section = self.statements.start_section(); let mut next = iter.next(); while next != Some(TokenKind::CloseCurly) { @@ -529,13 +463,14 @@ impl PassDefinitions { &module.source, iter.last_valid_pos(), "expected a statement or '}'" )); } - self.consume_statement(module, iter, ctx, &mut stmt_section)?; + let stmt_id = self.consume_statement(module, iter, ctx)?; + stmt_section.push(stmt_id); next = iter.next(); } let statements = stmt_section.into_vec(); let mut block_span = consume_token(&module.source, iter, TokenKind::CloseCurly)?; - block_span.begin = open_curly_pos; + block_span.begin = open_curly_span.begin; let id = ctx.heap.alloc_block_statement(|this| BlockStatement{ this, @@ -543,11 +478,7 @@ impl PassDefinitions { span: block_span, statements, end_block: EndBlockStatementId::new_invalid(), - scope_node: ScopeNode::new_invalid(), - first_unique_id_in_scope: -1, - next_unique_id_in_scope: -1, - locals: Vec::new(), - labels: Vec::new(), + scope: ScopeId::new_invalid(), next: StatementId::new_invalid(), }); @@ -568,24 +499,36 @@ impl PassDefinitions { consume_token(&module.source, iter, TokenKind::OpenParen)?; let test = self.consume_expression(module, iter, ctx)?; consume_token(&module.source, iter, TokenKind::CloseParen)?; - let true_body = self.consume_block_or_wrapped_statement(module, iter, ctx)?; - let false_body = if has_ident(&module.source, iter, KW_STMT_ELSE) { + let true_body = IfStatementCase{ + body: self.consume_statement(module, iter, ctx)?, + scope: ScopeId::new_invalid(), + }; + let true_body_scope_id = true_body.scope; + + let (false_body, false_body_scope_id) = if has_ident(&module.source, iter, KW_STMT_ELSE) { iter.consume(); - let false_body = self.consume_block_or_wrapped_statement(module, iter, ctx)?; - Some(false_body) + let false_body = IfStatementCase{ + body: self.consume_statement(module, iter, ctx)?, + scope: ScopeId::new_invalid(), + }; + + let false_body_scope_id = false_body.scope; + (Some(false_body), Some(false_body_scope_id)) } else { - None + (None, None) }; - Ok(ctx.heap.alloc_if_statement(|this| IfStatement{ + let if_stmt_id = ctx.heap.alloc_if_statement(|this| IfStatement{ this, span: if_span, test, - true_body, - false_body, + true_case: true_body, + false_case: false_body, end_if: EndIfStatementId::new_invalid(), - })) + }); + + return Ok(if_stmt_id); } fn consume_while_statement( @@ -595,12 +538,13 @@ impl PassDefinitions { consume_token(&module.source, iter, TokenKind::OpenParen)?; let test = self.consume_expression(module, iter, ctx)?; consume_token(&module.source, iter, TokenKind::CloseParen)?; - let body = self.consume_block_or_wrapped_statement(module, iter, ctx)?; + let body = self.consume_statement(module, iter, ctx)?; Ok(ctx.heap.alloc_while_statement(|this| WhileStatement{ this, span: while_span, test, + scope: ScopeId::new_invalid(), body, end_while: EndWhileStatementId::new_invalid(), in_sync: SynchronousStatementId::new_invalid(), @@ -649,11 +593,12 @@ impl PassDefinitions { &mut self, module: &Module, iter: &mut TokenIter, ctx: &mut PassCtx ) -> Result { let synchronous_span = consume_exact_ident(&module.source, iter, KW_STMT_SYNC)?; - let body = self.consume_block_or_wrapped_statement(module, iter, ctx)?; + let body = self.consume_statement(module, iter, ctx)?; Ok(ctx.heap.alloc_synchronous_statement(|this| SynchronousStatement{ this, span: synchronous_span, + scope: ScopeId::new_invalid(), body, end_sync: EndSynchronousStatementId::new_invalid(), })) @@ -663,11 +608,11 @@ impl PassDefinitions { &mut self, module: &Module, iter: &mut TokenIter, ctx: &mut PassCtx ) -> Result { let fork_span = consume_exact_ident(&module.source, iter, KW_STMT_FORK)?; - let left_body = self.consume_block_or_wrapped_statement(module, iter, ctx)?; + let left_body = self.consume_statement(module, iter, ctx)?; let right_body = if has_ident(&module.source, iter, KW_STMT_OR) { iter.consume(); - let right_body = self.consume_block_or_wrapped_statement(module, iter, ctx)?; + let right_body = self.consume_statement(module, iter, ctx)?; Some(right_body) } else { None @@ -710,9 +655,11 @@ impl PassDefinitions { }, }; consume_token(&module.source, iter, TokenKind::ArrowRight)?; - let block = self.consume_block_or_wrapped_statement(module, iter, ctx)?; + let block = self.consume_statement(module, iter, ctx)?; cases.push(SelectCase{ - guard, block, + guard, + body: block, + scope: ScopeId::new_invalid(), involved_ports: Vec::with_capacity(1) }); @@ -855,7 +802,7 @@ impl PassDefinitions { kind: VariableKind::Local, identifier: from_identifier, parser_type: from_port_type, - relative_pos_in_block: 0, + relative_pos_in_parent: 0, unique_id_in_scope: -1, }); @@ -870,7 +817,7 @@ impl PassDefinitions { kind: VariableKind::Local, identifier: to_identifier, parser_type: to_port_type, - relative_pos_in_block: 0, + relative_pos_in_parent: 0, unique_id_in_scope: -1, }); @@ -879,49 +826,25 @@ impl PassDefinitions { this, span: channel_span, from, to, - relative_pos_in_block: 0, + relative_pos_in_parent: 0, next: StatementId::new_invalid(), })) } - fn consume_labeled_statement( - &mut self, module: &Module, iter: &mut TokenIter, ctx: &mut PassCtx, section: &mut ScopedSection - ) -> Result<(), ParseError> { + fn consume_labeled_statement(&mut self, module: &Module, iter: &mut TokenIter, ctx: &mut PassCtx) -> Result { let label = consume_ident_interned(&module.source, iter, ctx)?; consume_token(&module.source, iter, TokenKind::Colon)?; - // Not pretty: consume_statement may produce more than one statement. - // The values in the section need to be in the correct order if some - // kind of outer block is consumed, so we take another section, push - // the expressions in that one, and then allocate the labeled statement. - let mut inner_section = self.statements.start_section(); - self.consume_statement(module, iter, ctx, &mut inner_section)?; - debug_assert!(inner_section.len() >= 1); - + let inner_stmt_id = self.consume_statement(module, iter, ctx)?; let stmt_id = ctx.heap.alloc_labeled_statement(|this| LabeledStatement { this, label, - body: inner_section[0], - relative_pos_in_block: 0, + body: inner_stmt_id, + relative_pos_in_parent: 0, in_sync: SynchronousStatementId::new_invalid(), }); - if inner_section.len() == 1 { - // Produce the labeled statement pointing to the first statement. - // This is by far the most common case. - inner_section.forget(); - section.push(stmt_id.upcast()); - } else { - // Produce the labeled statement using the first statement, and push - // the remaining ones at the end. - let inner_statements = inner_section.into_vec(); - section.push(stmt_id.upcast()); - for idx in 1..inner_statements.len() { - section.push(inner_statements[idx]) - } - } - - Ok(()) + return Ok(stmt_id); } /// Attempts to consume a memory statement (a statement along the lines of @@ -960,7 +883,7 @@ impl PassDefinitions { kind: VariableKind::Local, identifier: identifier.clone(), parser_type, - relative_pos_in_block: 0, + relative_pos_in_parent: 0, unique_id_in_scope: -1, }); @@ -1883,7 +1806,7 @@ fn consume_parameter_list( kind: VariableKind::Parameter, parser_type, identifier, - relative_pos_in_block: 0, + relative_pos_in_parent: 0, unique_id_in_scope: -1, }); Ok(parameter_id)