diff --git a/src/protocol/ast.rs b/src/protocol/ast.rs index ca6efe6af2637d61f1d1d50fa3cd87285916d4d0..6b2eaef1f425c59ef163f966967fb4a41daff97b 100644 --- a/src/protocol/ast.rs +++ b/src/protocol/ast.rs @@ -158,6 +158,8 @@ define_new_ast_id!(CastExpressionId, ExpressionId, index(CastExpression, Express define_new_ast_id!(CallExpressionId, ExpressionId, index(CallExpression, Expression::Call, expressions), alloc(alloc_call_expression)); define_new_ast_id!(VariableExpressionId, ExpressionId, index(VariableExpression, Expression::Variable, expressions), alloc(alloc_variable_expression)); +define_aliased_ast_id!(ScopeId, Id, index(Scope, scopes), alloc(alloc_scope)); + #[derive(Debug)] pub struct Heap { // Root arena, contains the entry point for different modules. Each root @@ -170,6 +172,7 @@ pub struct Heap { pub(crate) definitions: Arena, pub(crate) statements: Arena, pub(crate) expressions: Arena, + pub(crate) scopes: Arena, } impl Heap { @@ -183,6 +186,7 @@ impl Heap { definitions: Arena::new(), statements: Arena::new(), expressions: Arena::new(), + scopes: Arena::new(), } } pub fn alloc_memory_statement( @@ -705,57 +709,47 @@ impl<'a> Iterator for ConcreteTypeIter<'a> { } #[derive(Debug, Clone, Copy)] -pub enum Scope { +pub enum ScopeAssociation { Definition(DefinitionId), - Regular(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, - } - } - pub fn to_block(&self) -> BlockStatementId { - match &self { - Scope::Regular(id) => *id, - Scope::Synchronous(_, id) => *id, - _ => panic!("unable to get BlockStatement from Scope") - } - } + Block(BlockStatementId), + If(IfStatementId, bool), // if true, then body of "if", otherwise body of "else" + While(WhileStatementId), + Synchronous(SynchronousStatementId), + SelectCase(SelectStatementId, u32), // index is select case } /// `ScopeNode` is a helper that links scopes in two directions. It doesn't /// actually contain any information associated with the scope, this may be /// found on the AST elements that `Scope` points to. #[derive(Debug, Clone)] -pub struct ScopeNode { - pub parent: Scope, - pub nested: Vec, +pub struct Scope { + // Relation to other scopes + pub this: ScopeId, + pub parent: Option, + pub nested: Vec, + // Locally available variables/labels + pub association: ScopeAssociation, + pub variables: Vec, + pub labels: Vec, + // Location trackers/counters pub relative_pos_in_parent: i32, + pub first_unique_id_in_scope: i32, + pub next_unique_id_in_scope: i32, } -impl ScopeNode { - pub(crate) fn new_invalid() -> Self { - ScopeNode{ - parent: Scope::new_invalid(), +impl Scope { + pub(crate) fn new_invalid(this: ScopeId) -> Self { + return Self{ + this, + parent: None, nested: Vec::new(), + association: ScopeAssociation::Definition(DefinitionId::new_invalid()), + variables: Vec::new(), + labels: Vec::new(), relative_pos_in_parent: -1, - } + first_unique_id_in_scope: -1, + next_unique_id_in_scope: -1, + }; } } @@ -774,7 +768,7 @@ pub struct Variable { pub parser_type: ParserType, pub identifier: Identifier, // Validator/linker - pub relative_pos_in_block: i32, + pub relative_pos_in_parent: i32, pub unique_id_in_scope: i32, // Temporary fix until proper bytecode/asm is generated } @@ -1020,6 +1014,7 @@ pub struct ComponentDefinition { pub poly_vars: Vec, // Parsing pub parameters: Vec, + pub scope: ScopeId, pub body: BlockStatementId, // Validation/linking pub num_expressions_in_body: i32, @@ -1033,7 +1028,8 @@ impl ComponentDefinition { ) -> Self { Self{ this, defined_in, span, variant, identifier, poly_vars, - parameters: Vec::new(), + parameters: Vec::new(), + scope: ScopeId::new_invalid(), body: BlockStatementId::new_invalid(), num_expressions_in_body: -1, } @@ -1052,8 +1048,9 @@ pub struct FunctionDefinition { pub identifier: Identifier, pub poly_vars: Vec, // Parser - pub return_types: Vec, + pub return_type: ParserType, pub parameters: Vec, + pub scope: ScopeId, pub body: BlockStatementId, // Validation/linking pub num_expressions_in_body: i32, @@ -1068,8 +1065,9 @@ impl FunctionDefinition { this, defined_in, builtin: false, span, identifier, poly_vars, - return_types: Vec::new(), + return_type: ParserType{ elements: Vec::new(), full_span: InputSpan::new() }, parameters: Vec::new(), + scope: ScopeId::new_invalid(), body: BlockStatementId::new_invalid(), num_expressions_in_body: -1, } @@ -1178,6 +1176,7 @@ impl Statement { | Statement::If(_) => unreachable!(), } } + } #[derive(Debug, Clone)] @@ -1189,11 +1188,7 @@ pub struct BlockStatement { pub statements: Vec, pub end_block: EndBlockStatementId, // Phase 2: linker - 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 locals: Vec, - pub labels: Vec, + pub scope: ScopeId, pub next: StatementId, } @@ -1263,7 +1258,7 @@ pub struct ChannelStatement { pub from: VariableId, // output pub to: VariableId, // input // Phase 2: linker - pub relative_pos_in_block: i32, + pub relative_pos_in_parent: i32, pub next: StatementId, } @@ -1274,7 +1269,7 @@ pub struct LabeledStatement { pub label: Identifier, pub body: StatementId, // Phase 2: linker - pub relative_pos_in_block: i32, + pub relative_pos_in_parent: i32, pub in_sync: SynchronousStatementId, // may be invalid } @@ -1284,11 +1279,17 @@ pub struct IfStatement { // Phase 1: parser pub span: InputSpan, // of the "if" keyword pub test: ExpressionId, - pub true_body: BlockStatementId, - pub false_body: Option, + pub true_case: IfStatementCase, + pub false_case: Option, pub end_if: EndIfStatementId, } +#[derive(Debug, Clone, Copy)] +pub struct IfStatementCase { + pub body: StatementId, + pub scope: ScopeId, +} + #[derive(Debug, Clone)] pub struct EndIfStatement { pub this: EndIfStatementId, @@ -1302,7 +1303,8 @@ pub struct WhileStatement { // Phase 1: parser pub span: InputSpan, // of the "while" keyword pub test: ExpressionId, - pub body: BlockStatementId, + pub scope: ScopeId, + pub body: StatementId, pub end_while: EndWhileStatementId, pub in_sync: SynchronousStatementId, // may be invalid } @@ -1340,7 +1342,8 @@ pub struct SynchronousStatement { pub this: SynchronousStatementId, // Phase 1: parser pub span: InputSpan, // of the "sync" keyword - pub body: BlockStatementId, + pub scope: ScopeId, + pub body: StatementId, pub end_sync: EndSynchronousStatementId, } @@ -1357,8 +1360,8 @@ pub struct ForkStatement { pub this: ForkStatementId, // Phase 1: parser pub span: InputSpan, // of the "fork" keyword - pub left_body: BlockStatementId, - pub right_body: Option, + pub left_body: StatementId, + pub right_body: Option, pub end_fork: EndForkStatementId, } @@ -1382,7 +1385,8 @@ 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, + pub body: StatementId, + pub scope: ScopeId, // Phase 2: Validation and Linking pub involved_ports: Vec<(CallExpressionId, ExpressionId)>, // call to `get` and its port argument }