diff --git a/src/protocol/ast.rs b/src/protocol/ast.rs index da5ba6db6c6a05dde8bafa165679eda350dd7256..e137985fa110c6e2cea9a0f83be7cedf79aef88d 100644 --- a/src/protocol/ast.rs +++ b/src/protocol/ast.rs @@ -5,6 +5,7 @@ use std::ops::{Index, IndexMut}; use super::arena::{Arena, Id}; use crate::collections::StringRef; use crate::protocol::input_source::InputSpan; +use crate::protocol::TypeId; /// Helper macro that defines a type alias for a AST element ID. In this case /// only used to alias the `Id` types. @@ -117,8 +118,7 @@ define_aliased_ast_id!(DefinitionId, Id, index(Definition, definitio define_new_ast_id!(StructDefinitionId, DefinitionId, index(StructDefinition, Definition::Struct, definitions), alloc(alloc_struct_definition)); define_new_ast_id!(EnumDefinitionId, DefinitionId, index(EnumDefinition, Definition::Enum, definitions), alloc(alloc_enum_definition)); define_new_ast_id!(UnionDefinitionId, DefinitionId, index(UnionDefinition, Definition::Union, definitions), alloc(alloc_union_definition)); -define_new_ast_id!(ComponentDefinitionId, DefinitionId, index(ComponentDefinition, Definition::Component, definitions), alloc(alloc_component_definition)); -define_new_ast_id!(FunctionDefinitionId, DefinitionId, index(FunctionDefinition, Definition::Function, definitions), alloc(alloc_function_definition)); +define_new_ast_id!(ProcedureDefinitionId, DefinitionId, index(ProcedureDefinition, Definition::Procedure, definitions), alloc(alloc_procedure_definition)); define_aliased_ast_id!(StatementId, Id, index(Statement, statements)); define_new_ast_id!(BlockStatementId, StatementId, index(BlockStatement, Statement::Block, statements), alloc(alloc_block_statement)); @@ -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( @@ -210,14 +214,20 @@ impl Heap { impl Index for Heap { type Output = MemoryStatement; fn index(&self, index: MemoryStatementId) -> &Self::Output { - &self.statements[index.0.0].as_memory() + match &self.statements[index.0.0] { + Statement::Local(LocalStatement::Memory(v)) => v, + _ => unreachable!(), + } } } impl Index for Heap { type Output = ChannelStatement; fn index(&self, index: ChannelStatementId) -> &Self::Output { - &self.statements[index.0.0].as_channel() + match &self.statements[index.0.0] { + Statement::Local(LocalStatement::Channel(v)) => v, + _ => unreachable!(), + } } } @@ -340,6 +350,15 @@ pub struct Identifier { pub value: StringRef<'static>, } +impl Identifier { + pub(crate) const fn new_empty(span: InputSpan) -> Identifier { + return Identifier{ + span, + value: StringRef::new_empty(), + }; + } +} + impl PartialEq for Identifier { fn eq(&self, other: &Self) -> bool { return self.value == other.value @@ -497,12 +516,13 @@ pub enum ConcreteTypePart { Slice, Input, Output, + Pointer, // Tuple: variable number of nested types, will never be 1 Tuple(u32), // User defined type with any number of nested types Instance(DefinitionId, u32), // instance of data type - Function(DefinitionId, u32), // instance of function - Component(DefinitionId, u32), // instance of a connector + Function(ProcedureDefinitionId, u32), // instance of function + Component(ProcedureDefinitionId, u32), // instance of a connector } impl ConcreteTypePart { @@ -515,7 +535,7 @@ impl ConcreteTypePart { SInt8 | SInt16 | SInt32 | SInt64 | Character | String => 0, - Array | Slice | Input | Output => + Array | Slice | Input | Output | Pointer => 1, Tuple(num_embedded) => *num_embedded, Instance(_, num_embedded) => *num_embedded, @@ -622,6 +642,10 @@ impl ConcreteType { idx = Self::render_type_part_at(parts, heap, idx, target); target.push('>'); }, + CTP::Pointer => { + target.push('*'); + idx = Self::render_type_part_at(parts, heap, idx, target); + } CTP::Tuple(num_parts) => { target.push('('); if num_parts != 0 { @@ -633,27 +657,35 @@ impl ConcreteType { } target.push(')'); }, - CTP::Instance(definition_id, num_poly_args) | + CTP::Instance(definition_id, num_poly_args) => { + idx = Self::render_definition_type_parts_at(parts, heap, definition_id, num_poly_args, idx, target); + } CTP::Function(definition_id, num_poly_args) | CTP::Component(definition_id, num_poly_args) => { - let definition = &heap[definition_id]; - target.push_str(definition.identifier().value.as_str()); - - if num_poly_args != 0 { - target.push('<'); - for poly_arg_idx in 0..num_poly_args { - if poly_arg_idx != 0 { - target.push(','); - } - idx = Self::render_type_part_at(parts, heap, idx, target); - } - target.push('>'); - } + idx = Self::render_definition_type_parts_at(parts, heap, definition_id.upcast(), num_poly_args, idx, target); } } idx } + + fn render_definition_type_parts_at(parts: &[ConcreteTypePart], heap: &Heap, definition_id: DefinitionId, num_poly_args: u32, mut idx: usize, target: &mut String) -> usize { + let definition = &heap[definition_id]; + target.push_str(definition.identifier().value.as_str()); + + if num_poly_args != 0 { + target.push('<'); + for poly_arg_idx in 0..num_poly_args { + if poly_arg_idx != 0 { + target.push(','); + } + idx = Self::render_type_part_at(parts, heap, idx, target); + } + target.push('>'); + } + + return idx; + } } #[derive(Debug)] @@ -696,60 +728,66 @@ 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(id: ScopeId, association: ScopeAssociation) -> Self { + return Self{ + this: id, + parent: None, nested: Vec::new(), + association, + variables: Vec::new(), + labels: Vec::new(), relative_pos_in_parent: -1, + first_unique_id_in_scope: -1, + next_unique_id_in_scope: -1, } } } +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, + }; + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub enum VariableKind { Parameter, // in parameter list of function/component @@ -765,17 +803,16 @@ 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 } -#[derive(Debug, Clone)] +#[derive(Debug)] pub enum Definition { Struct(StructDefinition), Enum(EnumDefinition), Union(UnionDefinition), - Component(ComponentDefinition), - Function(FunctionDefinition), + Procedure(ProcedureDefinition), } impl Definition { @@ -827,71 +864,50 @@ impl Definition { _ => panic!("Unable to cast 'Definition' to 'UnionDefinition'"), } } + pub(crate) fn as_union_mut(&mut self) -> &mut UnionDefinition { match self { Definition::Union(result) => result, _ => panic!("Unable to cast 'Definition' to 'UnionDefinition'"), } } - pub fn is_component(&self) -> bool { - match self { - Definition::Component(_) => true, - _ => false, - } - } - pub(crate) fn as_component(&self) -> &ComponentDefinition { - match self { - Definition::Component(result) => result, - _ => panic!("Unable to cast `Definition` to `Component`"), - } - } - pub(crate) fn as_component_mut(&mut self) -> &mut ComponentDefinition { - match self { - Definition::Component(result) => result, - _ => panic!("Unable to cast `Definition` to `Component`"), - } - } - pub fn is_function(&self) -> bool { + + pub fn is_procedure(&self) -> bool { match self { - Definition::Function(_) => true, + Definition::Procedure(_) => true, _ => false, } } - pub(crate) fn as_function(&self) -> &FunctionDefinition { + + pub(crate) fn as_procedure(&self) -> &ProcedureDefinition { match self { - Definition::Function(result) => result, + Definition::Procedure(result) => result, _ => panic!("Unable to cast `Definition` to `Function`"), } } - pub(crate) fn as_function_mut(&mut self) -> &mut FunctionDefinition { + + pub(crate) fn as_procedure_mut(&mut self) -> &mut ProcedureDefinition { match self { - Definition::Function(result) => result, + Definition::Procedure(result) => result, _ => panic!("Unable to cast `Definition` to `Function`"), } } - pub fn parameters(&self) -> &Vec { - match self { - Definition::Component(def) => &def.parameters, - Definition::Function(def) => &def.parameters, - _ => panic!("Called parameters() on {:?}", self) - } - } + pub fn defined_in(&self) -> RootId { match self { Definition::Struct(def) => def.defined_in, Definition::Enum(def) => def.defined_in, Definition::Union(def) => def.defined_in, - Definition::Component(def) => def.defined_in, - Definition::Function(def) => def.defined_in, + Definition::Procedure(def) => def.defined_in, } } + pub fn identifier(&self) -> &Identifier { match self { Definition::Struct(def) => &def.identifier, Definition::Enum(def) => &def.identifier, Definition::Union(def) => &def.identifier, - Definition::Component(def) => &def.identifier, - Definition::Function(def) => &def.identifier, + Definition::Procedure(def) => &def.identifier, } } pub fn poly_vars(&self) -> &Vec { @@ -899,8 +915,7 @@ impl Definition { Definition::Struct(def) => &def.poly_vars, Definition::Enum(def) => &def.poly_vars, Definition::Union(def) => &def.poly_vars, - Definition::Component(def) => &def.poly_vars, - Definition::Function(def) => &def.poly_vars, + Definition::Procedure(def) => &def.poly_vars, } } } @@ -994,75 +1009,106 @@ impl UnionDefinition { } } -#[derive(Debug, Clone, Copy)] -pub enum ComponentVariant { - Primitive, +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ProcedureKind { + Function, // with return type + Primitive, // without return type Composite, } -#[derive(Debug, Clone)] -pub struct ComponentDefinition { - pub this: ComponentDefinitionId, - pub defined_in: RootId, - // Symbol scanning - pub span: InputSpan, - pub variant: ComponentVariant, - pub identifier: Identifier, - pub poly_vars: Vec, - // Parsing - pub parameters: Vec, - pub body: BlockStatementId, - // Validation/linking - pub num_expressions_in_body: i32, +/// Monomorphed instantiation of a procedure (or the sole instantiation of a +/// non-polymorphic procedure). +#[derive(Debug)] +pub struct ProcedureDefinitionMonomorph { + pub argument_types: Vec, + pub expr_info: Vec } -impl ComponentDefinition { - // Used for preallocation during symbol scanning - pub(crate) fn new_empty( - this: ComponentDefinitionId, defined_in: RootId, span: InputSpan, - variant: ComponentVariant, identifier: Identifier, poly_vars: Vec - ) -> Self { - Self{ - this, defined_in, span, variant, identifier, poly_vars, - parameters: Vec::new(), - body: BlockStatementId::new_invalid(), - num_expressions_in_body: -1, +impl ProcedureDefinitionMonomorph { + pub(crate) fn new_invalid() -> Self { + return Self{ + argument_types: Vec::new(), + expr_info: Vec::new(), + } + } +} + +#[derive(Debug, Clone, Copy)] +pub struct ExpressionInfo { + pub type_id: TypeId, + pub variant: ExpressionInfoVariant, +} + +impl ExpressionInfo { + pub(crate) fn new_invalid() -> Self { + return Self{ + type_id: TypeId::new_invalid(), + variant: ExpressionInfoVariant::Generic, + } + } +} + +#[derive(Debug, Clone, Copy)] +pub enum ExpressionInfoVariant { + Generic, + Procedure(TypeId, u32), // procedure TypeID and its monomorph index + Select(i32), // index +} + +impl ExpressionInfoVariant { + pub(crate) fn as_select(&self) -> i32 { + match self { + ExpressionInfoVariant::Select(v) => *v, + _ => unreachable!(), + } + } + + pub(crate) fn as_procedure(&self) -> (TypeId, u32) { + match self { + ExpressionInfoVariant::Procedure(type_id, monomorph_index) => (*type_id, *monomorph_index), + _ => unreachable!(), } } } +/// Generic storage for functions, primitive components and composite +/// components. // Note that we will have function definitions for builtin functions as well. In // that case the span, the identifier span and the body are all invalid. -#[derive(Debug, Clone)] -pub struct FunctionDefinition { - pub this: FunctionDefinitionId, +#[derive(Debug)] +pub struct ProcedureDefinition { + pub this: ProcedureDefinitionId, pub defined_in: RootId, // Symbol scanning pub builtin: bool, + pub kind: ProcedureKind, pub span: InputSpan, pub identifier: Identifier, pub poly_vars: Vec, // Parser - pub return_types: Vec, + pub return_type: Option, // present on functions, not components pub parameters: Vec, + pub scope: ScopeId, pub body: BlockStatementId, - // Validation/linking - pub num_expressions_in_body: i32, + // Monomorphization of typed procedures + pub monomorphs: Vec, } -impl FunctionDefinition { +impl ProcedureDefinition { pub(crate) fn new_empty( - this: FunctionDefinitionId, defined_in: RootId, span: InputSpan, - identifier: Identifier, poly_vars: Vec + this: ProcedureDefinitionId, defined_in: RootId, span: InputSpan, + kind: ProcedureKind, identifier: Identifier, poly_vars: Vec ) -> Self { Self { this, defined_in, builtin: false, - span, identifier, poly_vars, - return_types: Vec::new(), + span, + kind, identifier, poly_vars, + return_type: None, parameters: Vec::new(), + scope: ScopeId::new_invalid(), body: BlockStatementId::new_invalid(), - num_expressions_in_body: -1, + monomorphs: Vec::new(), } } } @@ -1092,25 +1138,6 @@ pub enum Statement { } impl Statement { - pub fn as_block(&self) -> &BlockStatement { - match self { - Statement::Block(result) => result, - _ => panic!("Unable to cast `Statement` to `BlockStatement`"), - } - } - pub fn as_local(&self) -> &LocalStatement { - match self { - Statement::Local(result) => result, - _ => panic!("Unable to cast `Statement` to `LocalStatement`"), - } - } - pub fn as_memory(&self) -> &MemoryStatement { - self.as_local().as_memory() - } - pub fn as_channel(&self) -> &ChannelStatement { - self.as_local().as_channel() - } - pub fn as_new(&self) -> &NewStatement { match self { Statement::New(result) => result, @@ -1169,22 +1196,18 @@ impl Statement { | Statement::If(_) => unreachable!(), } } + } #[derive(Debug, Clone)] pub struct BlockStatement { pub this: BlockStatementId, // Phase 1: parser - pub is_implicit: bool, pub span: InputSpan, // of the complete block 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, } @@ -1210,18 +1233,6 @@ impl LocalStatement { LocalStatement::Channel(stmt) => stmt.this.upcast(), } } - pub fn as_memory(&self) -> &MemoryStatement { - match self { - LocalStatement::Memory(result) => result, - _ => panic!("Unable to cast `LocalStatement` to `MemoryStatement`"), - } - } - pub fn as_channel(&self) -> &ChannelStatement { - match self { - LocalStatement::Channel(result) => result, - _ => panic!("Unable to cast `LocalStatement` to `ChannelStatement`"), - } - } pub fn span(&self) -> InputSpan { match self { LocalStatement::Channel(v) => v.span, @@ -1254,7 +1265,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, } @@ -1265,7 +1276,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 } @@ -1275,11 +1286,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, @@ -1293,7 +1310,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 } @@ -1331,7 +1349,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, } @@ -1348,8 +1367,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, } @@ -1366,6 +1385,8 @@ pub struct SelectStatement { pub span: InputSpan, // of the "select" keyword pub cases: Vec, pub end_select: EndSelectStatementId, + pub relative_pos_in_parent: i32, + pub next: StatementId, // note: the select statement will be transformed into other AST elements, this `next` jumps to those replacement statements } #[derive(Debug, Clone)] @@ -1373,7 +1394,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 } @@ -1432,7 +1454,7 @@ pub enum ExpressionParent { Return(ReturnStatementId), New(NewStatementId), ExpressionStmt(ExpressionStatementId), - Expression(ExpressionId, u32) // index within expression (e.g LHS or RHS of expression) + Expression(ExpressionId, u32) // index within expression (e.g LHS or RHS of expression, or index in array literal, etc.) } impl ExpressionParent { @@ -1530,6 +1552,23 @@ impl Expression { } } + pub fn parent_mut(&mut self) -> &mut ExpressionParent { + match self { + Expression::Assignment(expr) => &mut expr.parent, + Expression::Binding(expr) => &mut expr.parent, + Expression::Conditional(expr) => &mut expr.parent, + Expression::Binary(expr) => &mut expr.parent, + Expression::Unary(expr) => &mut expr.parent, + Expression::Indexing(expr) => &mut expr.parent, + Expression::Slicing(expr) => &mut expr.parent, + Expression::Select(expr) => &mut expr.parent, + Expression::Literal(expr) => &mut expr.parent, + Expression::Cast(expr) => &mut expr.parent, + Expression::Call(expr) => &mut expr.parent, + Expression::Variable(expr) => &mut expr.parent, + } + } + pub fn parent_expr_id(&self) -> Option { if let ExpressionParent::Expression(id, _) = self.parent() { Some(*id) @@ -1538,20 +1577,37 @@ impl Expression { } } - pub fn get_unique_id_in_definition(&self) -> i32 { + pub fn type_index(&self) -> i32 { + match self { + Expression::Assignment(expr) => expr.type_index, + Expression::Binding(expr) => expr.type_index, + Expression::Conditional(expr) => expr.type_index, + Expression::Binary(expr) => expr.type_index, + Expression::Unary(expr) => expr.type_index, + Expression::Indexing(expr) => expr.type_index, + Expression::Slicing(expr) => expr.type_index, + Expression::Select(expr) => expr.type_index, + Expression::Literal(expr) => expr.type_index, + Expression::Cast(expr) => expr.type_index, + Expression::Call(expr) => expr.type_index, + Expression::Variable(expr) => expr.type_index, + } + } + + pub fn type_index_mut(&mut self) -> &mut i32 { match self { - Expression::Assignment(expr) => expr.unique_id_in_definition, - Expression::Binding(expr) => expr.unique_id_in_definition, - Expression::Conditional(expr) => expr.unique_id_in_definition, - Expression::Binary(expr) => expr.unique_id_in_definition, - Expression::Unary(expr) => expr.unique_id_in_definition, - Expression::Indexing(expr) => expr.unique_id_in_definition, - Expression::Slicing(expr) => expr.unique_id_in_definition, - Expression::Select(expr) => expr.unique_id_in_definition, - Expression::Literal(expr) => expr.unique_id_in_definition, - Expression::Cast(expr) => expr.unique_id_in_definition, - Expression::Call(expr) => expr.unique_id_in_definition, - Expression::Variable(expr) => expr.unique_id_in_definition, + Expression::Assignment(expr) => &mut expr.type_index, + Expression::Binding(expr) => &mut expr.type_index, + Expression::Conditional(expr) => &mut expr.type_index, + Expression::Binary(expr) => &mut expr.type_index, + Expression::Unary(expr) => &mut expr.type_index, + Expression::Indexing(expr) => &mut expr.type_index, + Expression::Slicing(expr) => &mut expr.type_index, + Expression::Select(expr) => &mut expr.type_index, + Expression::Literal(expr) => &mut expr.type_index, + Expression::Cast(expr) => &mut expr.type_index, + Expression::Call(expr) => &mut expr.type_index, + Expression::Variable(expr) => &mut expr.type_index, } } } @@ -1583,7 +1639,8 @@ pub struct AssignmentExpression { pub right: ExpressionId, // Validator/Linker pub parent: ExpressionParent, - pub unique_id_in_definition: i32, + // Typing + pub type_index: i32, } #[derive(Debug, Clone)] @@ -1596,7 +1653,8 @@ pub struct BindingExpression { pub bound_from: ExpressionId, // Validator/Linker pub parent: ExpressionParent, - pub unique_id_in_definition: i32, + // Typing + pub type_index: i32, } #[derive(Debug, Clone)] @@ -1610,7 +1668,8 @@ pub struct ConditionalExpression { pub false_expression: ExpressionId, // Validator/Linking pub parent: ExpressionParent, - pub unique_id_in_definition: i32, + // Typing + pub type_index: i32, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -1647,7 +1706,8 @@ pub struct BinaryExpression { pub right: ExpressionId, // Validator/Linker pub parent: ExpressionParent, - pub unique_id_in_definition: i32, + // Typing + pub type_index: i32, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -1668,7 +1728,8 @@ pub struct UnaryExpression { pub expression: ExpressionId, // Validator/Linker pub parent: ExpressionParent, - pub unique_id_in_definition: i32, + // Typing + pub type_index: i32, } #[derive(Debug, Clone)] @@ -1681,7 +1742,8 @@ pub struct IndexingExpression { pub index: ExpressionId, // Validator/Linker pub parent: ExpressionParent, - pub unique_id_in_definition: i32, + // Typing + pub type_index: i32, } #[derive(Debug, Clone)] @@ -1695,7 +1757,8 @@ pub struct SlicingExpression { pub to_index: ExpressionId, // Validator/Linker pub parent: ExpressionParent, - pub unique_id_in_definition: i32, + // Typing + pub type_index: i32, } #[derive(Debug, Clone)] @@ -1714,7 +1777,8 @@ pub struct SelectExpression { pub kind: SelectKind, // Validator/Linker pub parent: ExpressionParent, - pub unique_id_in_definition: i32, + // Typing + pub type_index: i32, } #[derive(Debug, Clone)] @@ -1727,7 +1791,8 @@ pub struct CastExpression { pub subject: ExpressionId, // Validator/linker pub parent: ExpressionParent, - pub unique_id_in_definition: i32, + // Typing + pub type_index: i32, } #[derive(Debug, Clone)] @@ -1739,15 +1804,16 @@ pub struct CallExpression { pub parser_type: ParserType, // of the function call, not the return type pub method: Method, pub arguments: Vec, - pub definition: DefinitionId, + pub procedure: ProcedureDefinitionId, // Validator/Linker pub parent: ExpressionParent, - pub unique_id_in_definition: i32, + // Typing + pub type_index: i32, } #[derive(Debug, Clone, PartialEq, Eq)] pub enum Method { - // Builtin + // Builtin, accessible by programmer Get, Put, Fires, @@ -1755,14 +1821,31 @@ pub enum Method { Length, Assert, Print, + // Builtin, not accessible by programmer + SelectStart, // SelectStart(total_num_cases, total_num_ports) + SelectRegisterCasePort, // SelectRegisterCasePort(case_index, port_index, port_id) + SelectWait, // SelectWait() -> u32 + // User-defined UserFunction, UserComponent, } -#[derive(Debug, Clone)] -pub struct MethodSymbolic { - pub(crate) parser_type: ParserType, - pub(crate) definition: DefinitionId +impl Method { + pub(crate) fn is_public_builtin(&self) -> bool { + use Method::*; + match self { + Get | Put | Fires | Create | Length | Assert | Print => true, + _ => false, + } + } + + pub(crate) fn is_user_defined(&self) -> bool { + use Method::*; + match self { + UserFunction | UserComponent => true, + _ => false, + } + } } #[derive(Debug, Clone)] @@ -1773,7 +1856,8 @@ pub struct LiteralExpression { pub value: Literal, // Validator/Linker pub parent: ExpressionParent, - pub unique_id_in_definition: i32, + // Typing + pub type_index: i32, } #[derive(Debug, Clone)] @@ -1870,5 +1954,6 @@ pub struct VariableExpression { pub declaration: Option, pub used_as_binding_target: bool, pub parent: ExpressionParent, - pub unique_id_in_definition: i32, + // Typing + pub type_index: i32, } \ No newline at end of file