diff --git a/src/protocol/parser/pass_definitions.rs b/src/protocol/parser/pass_definitions.rs index c6b2f994762f6f61637e05f7c3fd29e8198a074b..af7df9289e33d4f14b041012aed4b6d3581b76fe 100644 --- a/src/protocol/parser/pass_definitions.rs +++ b/src/protocol/parser/pass_definitions.rs @@ -456,6 +456,19 @@ impl PassDefinitions { let fork_stmt = &mut ctx.heap[id]; fork_stmt.end_fork = end_fork; + } 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; } else if ident == KW_STMT_RETURN { let id = self.consume_return_statement(module, iter, ctx)?; section.push(id.upcast()); @@ -671,6 +684,44 @@ impl PassDefinitions { })) } + fn consume_select_statement( + &mut self, module: &Module, iter: &mut TokenIter, ctx: &mut PassCtx + ) -> Result { + let select_span = consume_exact_ident(&module.source, iter, KW_STMT_SELECT)?; + consume_token(&module.source, iter, TokenKind::OpenCurly)?; + + let mut cases = Vec::new(); + consume_comma_separated_until( + TokenKind::CloseCurly, &module.source, iter, ctx, + |source, iter, ctx| { + // A select arm starts with a guard, being something of the form + // `defined_var = get(port)`, `get(port)` or + // `Type var = get(port)`. So: + let (guard_var, guard_expr) = match self.maybe_consume_memory_statement(module, iter, ctx)? { + Some((guard_var, guard_expr)) => { + (Some(guard_var), guard_expr) + }, + None => { + let guard_expr = self.consume_expression_statement(module, iter, ctx)?; + (None, guard_expr) + }, + }; + consume_token(source, iter, TokenKind::ArrowRight)?; + let block = self.consume_block_or_wrapped_statement(module, iter, ctx)?; + + Ok(SelectCase{ guard_var, guard_expr, block }) + }, + &mut cases, "select arm", None + )?; + + Ok(ctx.heap.alloc_select_statement(|this| SelectStatement{ + this, + span: select_span, + cases, + end_select: EndSelectStatementId::new_invalid(), + })) + } + fn consume_return_statement( &mut self, module: &Module, iter: &mut TokenIter, ctx: &mut PassCtx ) -> Result {