diff --git a/src/protocol/ast.rs b/src/protocol/ast.rs index 782a5cbe5f3944cfaaaf6cafee08cde10226f41b..b1711f01c47b37b5fce11546146c2e432357abfb 100644 --- a/src/protocol/ast.rs +++ b/src/protocol/ast.rs @@ -117,8 +117,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)); @@ -214,14 +213,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!(), + } } } @@ -515,8 +520,8 @@ pub enum ConcreteTypePart { 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 { @@ -651,27 +656,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)] @@ -798,8 +811,7 @@ pub enum Definition { Struct(StructDefinition), Enum(EnumDefinition), Union(UnionDefinition), - Component(ComponentDefinition), - Function(FunctionDefinition), + Procedure(ProcedureDefinition), } impl Definition { @@ -851,71 +863,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 { @@ -923,8 +914,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, } } } @@ -1018,75 +1008,49 @@ 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 scope: ScopeId, - pub body: BlockStatementId, - // Validation/linking - pub num_expressions_in_body: i32, -} - -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(), - scope: ScopeId::new_invalid(), - body: BlockStatementId::new_invalid(), - num_expressions_in_body: -1, - } - } -} - +/// 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, +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_type: ParserType, + pub return_type: Option, // present on functions, not components pub parameters: Vec, pub scope: ScopeId, pub body: BlockStatementId, + // Monomorphization of typed procedures + // Validation/linking pub num_expressions_in_body: i32, } -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_type: ParserType{ elements: Vec::new(), full_span: InputSpan::new() }, + span, + kind, identifier, poly_vars, + return_type: None, parameters: Vec::new(), scope: ScopeId::new_invalid(), body: BlockStatementId::new_invalid(), @@ -1120,25 +1084,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, @@ -1234,18 +1179,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, @@ -1791,7 +1724,7 @@ 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, @@ -1812,7 +1745,7 @@ pub enum Method { SelectRegisterCasePort, // SelectRegisterCasePort(case_index, port_index, port_id) SelectWait, // SelectWait() -> u32 // User-defined - UserFunction, + UserProcedure, UserComponent, }