diff --git a/src/protocol/ast.rs b/src/protocol/ast.rs index 95195aef473b46c535fb2b034a712da10bf953ca..da5ba6db6c6a05dde8bafa165679eda350dd7256 100644 --- a/src/protocol/ast.rs +++ b/src/protocol/ast.rs @@ -137,6 +137,8 @@ define_new_ast_id!(SynchronousStatementId, StatementId, index(SynchronousStateme define_new_ast_id!(EndSynchronousStatementId, StatementId, index(EndSynchronousStatement, Statement::EndSynchronous, statements), alloc(alloc_end_synchronous_statement)); define_new_ast_id!(ForkStatementId, StatementId, index(ForkStatement, Statement::Fork, statements), alloc(alloc_fork_statement)); define_new_ast_id!(EndForkStatementId, StatementId, index(EndForkStatement, Statement::EndFork, statements), alloc(alloc_end_fork_statement)); +define_new_ast_id!(SelectStatementId, StatementId, index(SelectStatement, Statement::Select, statements), alloc(alloc_select_statement)); +define_new_ast_id!(EndSelectStatementId, StatementId, index(EndSelectStatement, Statement::EndSelect, statements), alloc(alloc_end_select_statement)); define_new_ast_id!(ReturnStatementId, StatementId, index(ReturnStatement, Statement::Return, statements), alloc(alloc_return_statement)); define_new_ast_id!(GotoStatementId, StatementId, index(GotoStatement, Statement::Goto, statements), alloc(alloc_goto_statement)); define_new_ast_id!(NewStatementId, StatementId, index(NewStatement, Statement::New, statements), alloc(alloc_new_statement)); @@ -697,21 +699,32 @@ impl<'a> Iterator for ConcreteTypeIter<'a> { pub enum Scope { Definition(DefinitionId), Regular(BlockStatementId), - Synchronous((SynchronousStatementId, BlockStatementId)), + Synchronous(SynchronousStatementId, BlockStatementId), } impl Scope { + pub(crate) fn new_invalid() -> Scope { + return Scope::Definition(DefinitionId::new_invalid()); + } + + pub(crate) fn is_invalid(&self) -> bool { + match self { + Scope::Definition(id) => id.is_invalid(), + _ => false, + } + } + pub fn is_block(&self) -> bool { match &self { Scope::Definition(_) => false, Scope::Regular(_) => true, - Scope::Synchronous(_) => true, + Scope::Synchronous(_, _) => true, } } pub fn to_block(&self) -> BlockStatementId { match &self { Scope::Regular(id) => *id, - Scope::Synchronous((_, id)) => *id, + Scope::Synchronous(_, id) => *id, _ => panic!("unable to get BlockStatement from Scope") } } @@ -724,13 +737,15 @@ impl Scope { pub struct ScopeNode { pub parent: Scope, pub nested: Vec, + pub relative_pos_in_parent: i32, } impl ScopeNode { pub(crate) fn new_invalid() -> Self { ScopeNode{ - parent: Scope::Definition(DefinitionId::new_invalid()), + parent: Scope::new_invalid(), nested: Vec::new(), + relative_pos_in_parent: -1, } } } @@ -750,7 +765,7 @@ pub struct Variable { pub parser_type: ParserType, pub identifier: Identifier, // Validator/linker - pub relative_pos_in_block: u32, + pub relative_pos_in_block: i32, pub unique_id_in_scope: i32, // Temporary fix until proper bytecode/asm is generated } @@ -1068,6 +1083,8 @@ pub enum Statement { EndSynchronous(EndSynchronousStatement), Fork(ForkStatement), EndFork(EndForkStatement), + Select(SelectStatement), + EndSelect(EndSelectStatement), Return(ReturnStatement), Goto(GotoStatement), New(NewStatement), @@ -1112,11 +1129,17 @@ impl Statement { Statement::Continue(v) => v.span, Statement::Synchronous(v) => v.span, Statement::Fork(v) => v.span, + Statement::Select(v) => v.span, Statement::Return(v) => v.span, Statement::Goto(v) => v.span, Statement::New(v) => v.span, Statement::Expression(v) => v.span, - Statement::EndBlock(_) | Statement::EndIf(_) | Statement::EndWhile(_) | Statement::EndSynchronous(_) | Statement::EndFork(_) => unreachable!(), + Statement::EndBlock(_) + | Statement::EndIf(_) + | Statement::EndWhile(_) + | Statement::EndSynchronous(_) + | Statement::EndFork(_) + | Statement::EndSelect(_) => unreachable!(), } } pub fn link_next(&mut self, next: StatementId) { @@ -1131,6 +1154,7 @@ impl Statement { Statement::EndWhile(stmt) => stmt.next = next, Statement::EndSynchronous(stmt) => stmt.next = next, Statement::EndFork(stmt) => stmt.next = next, + Statement::EndSelect(stmt) => stmt.next = next, Statement::New(stmt) => stmt.next = next, Statement::Expression(stmt) => stmt.next = next, Statement::Return(_) @@ -1138,6 +1162,7 @@ impl Statement { | Statement::Continue(_) | Statement::Synchronous(_) | Statement::Fork(_) + | Statement::Select(_) | Statement::Goto(_) | Statement::While(_) | Statement::Labeled(_) @@ -1158,7 +1183,6 @@ pub struct BlockStatement { pub scope_node: ScopeNode, pub first_unique_id_in_scope: i32, // Temporary fix until proper bytecode/asm is generated pub next_unique_id_in_scope: i32, // Temporary fix until proper bytecode/asm is generated - pub relative_pos_in_parent: u32, pub locals: Vec, pub labels: Vec, pub next: StatementId, @@ -1212,6 +1236,7 @@ pub struct MemoryStatement { // Phase 1: parser pub span: InputSpan, pub variable: VariableId, + pub initial_expr: AssignmentExpressionId, // Phase 2: linker pub next: StatementId, } @@ -1229,7 +1254,7 @@ pub struct ChannelStatement { pub from: VariableId, // output pub to: VariableId, // input // Phase 2: linker - pub relative_pos_in_block: u32, + pub relative_pos_in_block: i32, pub next: StatementId, } @@ -1240,7 +1265,7 @@ pub struct LabeledStatement { pub label: Identifier, pub body: StatementId, // Phase 2: linker - pub relative_pos_in_block: u32, + pub relative_pos_in_block: i32, pub in_sync: SynchronousStatementId, // may be invalid } @@ -1288,7 +1313,7 @@ pub struct BreakStatement { pub span: InputSpan, // of the "break" keyword pub label: Option, // Phase 2: linker - pub target: Option, + pub target: EndWhileStatementId, // invalid if not yet set } #[derive(Debug, Clone)] @@ -1298,7 +1323,7 @@ pub struct ContinueStatement { pub span: InputSpan, // of the "continue" keyword pub label: Option, // Phase 2: linker - pub target: Option, + pub target: WhileStatementId, // invalid if not yet set } #[derive(Debug, Clone)] @@ -1335,6 +1360,31 @@ pub struct EndForkStatement { pub next: StatementId, } +#[derive(Debug, Clone)] +pub struct SelectStatement { + pub this: SelectStatementId, + pub span: InputSpan, // of the "select" keyword + pub cases: Vec, + pub end_select: EndSelectStatementId, +} + +#[derive(Debug, Clone)] +pub struct SelectCase { + // The guard statement of a `select` is either a MemoryStatement or an + // ExpressionStatement. Nothing else is allowed by the initial parsing + pub guard: StatementId, + pub block: BlockStatementId, + // Phase 2: Validation and Linking + pub involved_ports: Vec<(CallExpressionId, ExpressionId)>, // call to `get` and its port argument +} + +#[derive(Debug, Clone)] +pub struct EndSelectStatement { + pub this: EndSelectStatementId, + pub start_select: SelectStatementId, + pub next: StatementId, +} + #[derive(Debug, Clone)] pub struct ReturnStatement { pub this: ReturnStatementId, @@ -1350,7 +1400,7 @@ pub struct GotoStatement { pub span: InputSpan, // of the "goto" keyword pub label: Identifier, // Phase 2: linker - pub target: Option, + pub target: LabeledStatementId, // invalid if not yet set } #[derive(Debug, Clone)] @@ -1376,6 +1426,7 @@ pub struct ExpressionStatement { #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum ExpressionParent { None, // only set during initial parsing + Memory(MemoryStatementId), If(IfStatementId), While(WhileStatementId), Return(ReturnStatementId),