From c6a9e4f128f2fd319fae825704da49a28ab31671 2022-02-23 17:22:13 From: mh Date: 2022-02-23 17:22:13 Subject: [PATCH] Unified component/function data into procedure --- diff --git a/src/collections/raw_vec.rs b/src/collections/raw_vec.rs index a506831c8f86d3fe80bc93e9030a7b89a1fbeaef..91ecb47b9c7f79f7d79db83ed638628104da6a22 100644 --- a/src/collections/raw_vec.rs +++ b/src/collections/raw_vec.rs @@ -62,20 +62,6 @@ impl RawVec { } } - /// Moves the elements in the range [from_idx, from_idx + num_to_move) to - /// the range [to_idx, to_idx + num_to_move). Caller must make sure that all - /// non-overlapping elements of the second range had their destructor called - /// in case those elements were used. - pub fn move_range(&mut self, from_idx: usize, to_idx: usize, num_to_move: usize) { - debug_assert!(from_idx + num_to_move <= self.len); - debug_assert!(to_idx + num_to_move <= self.len); // maybe not in future, for now this is fine - unsafe { - let source = self.base.add(from_idx); - let target = self.base.add(to_idx); - std::ptr::copy(source, target, num_to_move); - } - } - pub fn len(&self) -> usize { return self.len; } 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, } diff --git a/src/protocol/ast_printer.rs b/src/protocol/ast_printer.rs index 73f14dfd7e8a3552f0106030101aff683ceca2d6..a64b56f724bf3f8e7ccf788fa9e740f5628db24e 100644 --- a/src/protocol/ast_printer.rs +++ b/src/protocol/ast_printer.rs @@ -345,7 +345,7 @@ impl ASTWriter { } } } - Definition::Function(def) => { + Definition::Procedure(def) => { self.kv(indent).with_id(PREFIX_FUNCTION_ID, def.this.0.index) .with_s_key("DefinitionFunction"); @@ -354,8 +354,11 @@ impl ASTWriter { self.kv(indent3).with_s_key("PolyVar").with_identifier_val(&poly_var_id); } - self.kv(indent2).with_s_key("ReturnParserType") - .with_custom_val(|s| write_parser_type(s, heap, &def.return_type)); + self.kv(indent2).with_s_key("Kind").with_debug_val(&def.kind); + if let Some(parser_type) = &def.return_type { + self.kv(indent2).with_s_key("ReturnParserType") + .with_custom_val(|s| write_parser_type(s, heap, parser_type)); + } self.kv(indent2).with_s_key("Parameters"); for variable_id in &def.parameters { @@ -365,26 +368,6 @@ impl ASTWriter { self.kv(indent2).with_s_key("Body"); self.write_stmt(heap, def.body.upcast(), indent3); }, - Definition::Component(def) => { - self.kv(indent).with_id(PREFIX_COMPONENT_ID,def.this.0.index) - .with_s_key("DefinitionComponent"); - - self.kv(indent2).with_s_key("Name").with_identifier_val(&def.identifier); - self.kv(indent2).with_s_key("Variant").with_debug_val(&def.variant); - - self.kv(indent2).with_s_key("PolymorphicVariables"); - for poly_var_id in &def.poly_vars { - self.kv(indent3).with_s_key("PolyVar").with_identifier_val(&poly_var_id); - } - - self.kv(indent2).with_s_key("Parameters"); - for variable_id in &def.parameters { - self.write_variable(heap, *variable_id, indent3) - } - - self.kv(indent2).with_s_key("Body"); - self.write_stmt(heap, def.body.upcast(), indent3); - } } } @@ -782,19 +765,11 @@ impl ASTWriter { .with_s_key("CallExpr"); self.kv(indent2).with_s_key("UniqueId").with_disp_val(&expr.unique_id_in_definition); - let definition = &heap[expr.definition]; - match definition { - Definition::Component(definition) => { - self.kv(indent2).with_s_key("BuiltIn").with_disp_val(&false); - self.kv(indent2).with_s_key("Variant").with_debug_val(&definition.variant); - }, - Definition::Function(definition) => { - self.kv(indent2).with_s_key("BuiltIn").with_disp_val(&definition.builtin); - self.kv(indent2).with_s_key("Variant").with_s_val("Function"); - }, - _ => unreachable!() - } - self.kv(indent2).with_s_key("MethodName").with_identifier_val(definition.identifier()); + + let definition = &heap[expr.procedure]; + self.kv(indent2).with_s_key("BuiltIn").with_disp_val(&false); + self.kv(indent2).with_s_key("Variant").with_debug_val(&definition.kind); + self.kv(indent2).with_s_key("MethodName").with_identifier_val(&definition.identifier); self.kv(indent2).with_s_key("ParserType") .with_custom_val(|t| write_parser_type(t, heap, &expr.parser_type)); diff --git a/src/protocol/eval/error.rs b/src/protocol/eval/error.rs index fc194bb37c8ef31e8084d2613f4cdb9b9a36a344..81128b445a5c36ed8cda7034b2ca9d2f99084a8e 100644 --- a/src/protocol/eval/error.rs +++ b/src/protocol/eval/error.rs @@ -52,18 +52,8 @@ impl EvalError { let statement = &heap[frame.position]; let statement_span = statement.span(); - let (root_id, procedure, is_func) = match definition { - Definition::Function(def) => { - (def.defined_in, def.identifier.value.as_str().to_string(), true) - }, - Definition::Component(def) => { - (def.defined_in, def.identifier.value.as_str().to_string(), false) - }, - _ => unreachable!("construct stack frame with definition pointing to data type") - }; - // Lookup module name, if it has one - let module = modules.iter().find(|m| m.root_id == root_id).unwrap(); + let module = modules.iter().find(|m| m.root_id == definition.defined_in).unwrap(); let module_name = if let Some(name) = &module.name { name.as_str().to_string() } else { @@ -74,8 +64,8 @@ impl EvalError { frames.push(EvalFrame{ line: statement_span.begin.line, module_name, - procedure, - is_func + procedure: definition.identifier.value.as_str().to_string(), + is_func: definition.kind == ProcedureKind::Function, }); } diff --git a/src/protocol/eval/executor.rs b/src/protocol/eval/executor.rs index 9bda8f7069a6e45e9f51dcb19b4f8757f94517f2..0adc2ab8e4b87ff2b35cf6bea6f6286f39e49683 100644 --- a/src/protocol/eval/executor.rs +++ b/src/protocol/eval/executor.rs @@ -26,7 +26,7 @@ pub(crate) enum ExprInstruction { #[derive(Debug, Clone)] pub(crate) struct Frame { - pub(crate) definition: DefinitionId, + pub(crate) definition: ProcedureDefinitionId, pub(crate) monomorph_type_id: TypeId, pub(crate) position: StatementId, pub(crate) expr_stack: VecDeque, // hack for expression evaluation, evaluated by popping from back @@ -36,13 +36,10 @@ pub(crate) struct Frame { impl Frame { /// Creates a new execution frame. Does not modify the stack in any way. - pub fn new(heap: &Heap, definition_id: DefinitionId, monomorph_type_id: TypeId) -> Self { + pub fn new(heap: &Heap, definition_id: ProcedureDefinitionId, monomorph_type_id: TypeId) -> Self { let definition = &heap[definition_id]; - let (outer_scope_id, first_statement_id) = match definition { - Definition::Component(definition) => (definition.scope, definition.body), - Definition::Function(definition) => (definition.scope, definition.body), - _ => unreachable!("initializing frame with {:?} instead of a function/component", definition), - }; + let outer_scope_id = definition.scope; + let first_statement_id = definition.body; // Another not-so-pretty thing that has to be replaced somewhere in the // future... @@ -211,7 +208,7 @@ pub enum EvalContinuation { // Returned only in non-sync mode ComponentTerminated, SyncBlockStart, - NewComponent(DefinitionId, TypeId, ValueGroup), + NewComponent(ProcedureDefinitionId, TypeId, ValueGroup), NewChannel, } @@ -224,7 +221,7 @@ pub struct Prompt { } impl Prompt { - pub fn new(_types: &TypeTable, heap: &Heap, def: DefinitionId, type_id: TypeId, args: ValueGroup) -> Self { + pub fn new(_types: &TypeTable, heap: &Heap, def: ProcedureDefinitionId, type_id: TypeId, args: ValueGroup) -> Self { let mut prompt = Self{ frames: Vec::new(), store: Store::new(), @@ -291,7 +288,7 @@ impl Prompt { // Checking if we're at the end of execution let cur_frame = self.frames.last_mut().unwrap(); if cur_frame.position.is_invalid() { - if heap[cur_frame.definition].is_function() { + if heap[cur_frame.definition].kind == ProcedureKind::Function { todo!("End of function without return, return an evaluation error"); } return Ok(EvalContinuation::ComponentTerminated); @@ -745,10 +742,10 @@ impl Prompt { Method::UserComponent => { // This is actually handled by the evaluation // of the statement. - debug_assert_eq!(heap[expr.definition].parameters().len(), cur_frame.expr_values.len()); + debug_assert_eq!(heap[expr.procedure].parameters.len(), cur_frame.expr_values.len()); debug_assert_eq!(heap[cur_frame.position].as_new().expression, expr.this) }, - Method::UserFunction => { + Method::UserProcedure => { // Push a new frame. Note that all expressions have // been pushed to the front, so they're in the order // of the definition. @@ -770,7 +767,7 @@ impl Prompt { let call_data = &mono_data.expr_data[expr.unique_id_in_definition as usize]; // Push the new frame and reserve its stack size - let new_frame = Frame::new(heap, expr.definition, call_data.type_id); + let new_frame = Frame::new(heap, expr.procedure, call_data.type_id); let new_stack_size = new_frame.max_stack_size; self.frames.push(new_frame); self.store.cur_stack_boundary = new_stack_boundary; @@ -779,7 +776,7 @@ impl Prompt { // To simplify the logic a little bit we will now // return and ask our caller to call us again return Ok(EvalContinuation::Stepping); - }, + } } }, Expression::Variable(expr) => { @@ -977,7 +974,6 @@ impl Prompt { Ok(EvalContinuation::Stepping) }, Statement::Return(_stmt) => { - debug_assert!(heap[cur_frame.definition].is_function()); debug_assert_eq!(cur_frame.expr_values.len(), 1, "expected one expr value for return statement"); // The preceding frame has executed a call, so is expecting the @@ -1024,9 +1020,8 @@ impl Prompt { }, Statement::New(stmt) => { let call_expr = &heap[stmt.expression]; - debug_assert!(heap[call_expr.definition].is_component()); debug_assert_eq!( - cur_frame.expr_values.len(), heap[call_expr.definition].parameters().len(), + cur_frame.expr_values.len(), heap[call_expr.procedure].parameters.len(), "mismatch in expr stack size and number of arguments for new statement" ); @@ -1052,7 +1047,7 @@ impl Prompt { cur_frame.position = stmt.next; - Ok(EvalContinuation::NewComponent(call_expr.definition, expr_data.type_id, argument_group)) + Ok(EvalContinuation::NewComponent(call_expr.procedure, expr_data.type_id, argument_group)) }, Statement::Expression(stmt) => { // The expression has just been completely evaluated. Some diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 11a19bd3ffbdc35734f7290fdbe9bad6d3276054..9a41b28c25581af0f1467043b1f9c21082f5e794 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -94,20 +94,20 @@ impl ProtocolDescription { let definition_id = definition_id.unwrap(); let ast_definition = &self.heap[definition_id]; - if !ast_definition.is_component() { + if !ast_definition.is_procedure() { return Err(ComponentCreationError::DefinitionNotComponent); } // Make sure that the types of the provided value group matches that of // the expected types. - let ast_definition = ast_definition.as_component(); - if !ast_definition.poly_vars.is_empty() { + let ast_definition = ast_definition.as_procedure(); + if !ast_definition.poly_vars.is_empty() || ast_definition.kind == ProcedureKind::Function { return Err(ComponentCreationError::DefinitionNotComponent); } // - check number of arguments by retrieving the one instantiated // monomorph - let concrete_type = ConcreteType{ parts: vec![ConcreteTypePart::Component(definition_id, 0)] }; + let concrete_type = ConcreteType{ parts: vec![ConcreteTypePart::Component(ast_definition.this, 0)] }; let mono_index = self.types.get_procedure_monomorph_type_id(&definition_id, &concrete_type.parts).unwrap(); let mono_type = self.types.get_procedure_monomorph(mono_index); if mono_type.arg_types.len() != arguments.values.len() { @@ -125,7 +125,7 @@ impl ProtocolDescription { // By now we're sure that all of the arguments are correct. So create // the connector. - return Ok(Prompt::new(&self.types, &self.heap, definition_id, mono_index, arguments)); + return Ok(Prompt::new(&self.types, &self.heap, ast_definition.this, mono_index, arguments)); } fn lookup_module_root(&self, module_name: &[u8]) -> Option { diff --git a/src/protocol/parser/mod.rs b/src/protocol/parser/mod.rs index 73fdd6dfcd496c0ec23042d8c6bb0c6272a57d99..9ef01e4a58319347b06620e5b7012a140d093c5d 100644 --- a/src/protocol/parser/mod.rs +++ b/src/protocol/parser/mod.rs @@ -324,8 +324,8 @@ impl Parser { types: &mut self.type_table, arch: &self.arch, }; - self.pass_rewriting.visit_module(&mut ctx); - self.pass_stack_size.visit_module(&mut ctx); + self.pass_rewriting.visit_module(&mut ctx)?; + self.pass_stack_size.visit_module(&mut ctx)?; } // Write out desired information @@ -356,7 +356,7 @@ fn insert_builtin_type(type_table: &mut TypeTable, parts: Vec, } // Note: args and return type need to be a function because we need to know the function ID. -fn insert_builtin_function (Vec<(&'static str, ParserType)>, ParserType)> ( +fn insert_builtin_function (Vec<(&'static str, ParserType)>, ParserType)> ( p: &mut Parser, func_name: &str, polymorphic: &[&str], arg_and_return_fn: T ) { let mut poly_vars = Vec::with_capacity(polymorphic.len()); @@ -365,21 +365,22 @@ fn insert_builtin_function (Vec<(&'static str, Pa } let func_ident_ref = p.string_pool.intern(func_name.as_bytes()); - let func_id = p.heap.alloc_function_definition(|this| FunctionDefinition{ + let procedure_id = p.heap.alloc_procedure_definition(|this| ProcedureDefinition { this, defined_in: RootId::new_invalid(), builtin: true, + kind: ProcedureKind::Function, span: InputSpan::new(), identifier: Identifier{ span: InputSpan::new(), value: func_ident_ref.clone() }, poly_vars, - return_type: ParserType{ elements: Vec::new(), full_span: InputSpan::new() }, + return_type: None, parameters: Vec::new(), scope: ScopeId::new_invalid(), body: BlockStatementId::new_invalid(), num_expressions_in_body: -1, }); - let (arguments, return_type) = arg_and_return_fn(func_id); + let (arguments, return_type) = arg_and_return_fn(procedure_id); let mut parameters = Vec::with_capacity(arguments.len()); for (arg_name, arg_type) in arguments { @@ -395,9 +396,9 @@ fn insert_builtin_function (Vec<(&'static str, Pa parameters.push(param_id); } - let func = &mut p.heap[func_id]; + let func = &mut p.heap[procedure_id]; func.parameters = parameters; - func.return_type = return_type; + func.return_type = Some(return_type); p.symbol_table.insert_symbol(SymbolScope::Global, Symbol{ name: func_ident_ref, @@ -408,7 +409,7 @@ fn insert_builtin_function (Vec<(&'static str, Pa identifier_span: InputSpan::new(), imported_at: None, class: DefinitionClass::Function, - definition_id: func_id.upcast(), + definition_id: procedure_id.upcast(), }) }).unwrap(); } \ No newline at end of file diff --git a/src/protocol/parser/pass_definitions.rs b/src/protocol/parser/pass_definitions.rs index 6a97cc63dd144569b731a0250ff410a327728d4a..303d9ec425c5551f0e2a93ea8ba656fd2d27687a 100644 --- a/src/protocol/parser/pass_definitions.rs +++ b/src/protocol/parser/pass_definitions.rs @@ -284,8 +284,8 @@ impl PassDefinitions { let scope_id = ctx.heap.alloc_scope(|this| Scope::new(this, ScopeAssociation::Definition(definition_id))); // Assign everything in the preallocated AST node - let function = ctx.heap[definition_id].as_function_mut(); - function.return_type = parser_type; + let function = ctx.heap[definition_id].as_procedure_mut(); + function.return_type = Some(parser_type); function.parameters = parameters; function.scope = scope_id; function.body = body_id; @@ -321,7 +321,8 @@ impl PassDefinitions { let scope_id = ctx.heap.alloc_scope(|this| Scope::new(this, ScopeAssociation::Definition(definition_id))); // Assign everything in the AST node - let component = ctx.heap[definition_id].as_component_mut(); + let component = ctx.heap[definition_id].as_procedure_mut(); + debug_assert!(component.return_type.is_none()); component.parameters = parameters; component.scope = scope_id; component.body = body_id; @@ -758,7 +759,7 @@ impl PassDefinitions { if let Expression::Call(expression) = expression { // Allow both components and functions, as it makes more sense to // check their correct use in the validation and linking pass - if expression.method == Method::UserComponent || expression.method == Method::UserFunction { + if expression.method == Method::UserComponent || expression.method == Method::UserProcedure { call_id = expression.this; valid = true; } @@ -1576,28 +1577,11 @@ impl PassDefinitions { unique_id_in_definition: -1, }).upcast() }, - Definition::Component(_) => { - // Component instantiation - let func_span = parser_type.full_span; - let mut full_span = func_span; - let arguments = self.consume_expression_list( - module, iter, ctx, Some(&mut full_span.end) - )?; - - ctx.heap.alloc_call_expression(|this| CallExpression{ - this, func_span, full_span, - parser_type, - method: Method::UserComponent, - arguments, - definition: target_definition_id, - parent: ExpressionParent::None, - unique_id_in_definition: -1, - }).upcast() - }, - Definition::Function(function_definition) => { + Definition::Procedure(proc_def) => { // Check whether it is a builtin function - let method = if function_definition.builtin { - match function_definition.identifier.value.as_bytes() { + let procedure_id = proc_def.this; + let method = if proc_def.builtin { + match proc_def.identifier.value.as_bytes() { KW_FUNC_GET => Method::Get, KW_FUNC_PUT => Method::Put, KW_FUNC_FIRES => Method::Fires, @@ -1607,8 +1591,10 @@ impl PassDefinitions { KW_FUNC_PRINT => Method::Print, _ => unreachable!(), } + } else if proc_def.kind == ProcedureKind::Function { + Method::UserProcedure } else { - Method::UserFunction + Method::UserComponent }; // Function call: consume the arguments @@ -1620,7 +1606,7 @@ impl PassDefinitions { ctx.heap.alloc_call_expression(|this| CallExpression{ this, func_span, full_span, parser_type, method, arguments, - definition: target_definition_id, + procedure: procedure_id, parent: ExpressionParent::None, unique_id_in_definition: -1, }).upcast() diff --git a/src/protocol/parser/pass_rewriting.rs b/src/protocol/parser/pass_rewriting.rs index 54b7c3b8d91feaafe05f565a28351992e0fffe24..640f4cf286afc7a09790dae0f3539cb163000cb5 100644 --- a/src/protocol/parser/pass_rewriting.rs +++ b/src/protocol/parser/pass_rewriting.rs @@ -45,17 +45,10 @@ impl Visitor for PassRewriting { // --- Visiting procedures - fn visit_component_definition(&mut self, ctx: &mut Ctx, id: ComponentDefinitionId) -> VisitorResult { - let def = &ctx.heap[id]; - let body_id = def.body; - self.current_scope = def.scope; - return self.visit_block_stmt(ctx, body_id); - } - - fn visit_function_definition(&mut self, ctx: &mut Ctx, id: FunctionDefinitionId) -> VisitorResult { - let def = &ctx.heap[id]; - let body_id = def.body; - self.current_scope = def.scope; + fn visit_procedure_definition(&mut self, ctx: &mut Ctx, id: ProcedureDefinitionId) -> VisitorResult { + let definition = &ctx.heap[id]; + let body_id = definition.body; + self.current_scope = definition.scope; return self.visit_block_stmt(ctx, body_id); } @@ -162,7 +155,7 @@ impl Visitor for PassRewriting { let total_num_cases = select_stmt.cases.len(); let mut total_num_ports = 0; let end_select_stmt_id = select_stmt.end_select; - let end_select = &ctx.heap[end_select_stmt_id]; + let _end_select = &ctx.heap[end_select_stmt_id]; // Put heap IDs into temporary buffers to handle borrowing rules let mut call_id_section = self.call_expr_buffer.start_section(); @@ -313,7 +306,7 @@ impl PassRewriting { }, method, arguments, - definition: DefinitionId::new_invalid(), + procedure: ProcedureDefinitionId::new_invalid(), parent: ExpressionParent::None, unique_id_in_definition: -1, }); @@ -376,7 +369,7 @@ fn create_ast_call_expr(ctx: &mut Ctx, method: Method, buffer: &mut ScopedBuffer }, method, arguments, - definition: DefinitionId::new_invalid(), + procedure: ProcedureDefinitionId::new_invalid(), parent: ExpressionParent::None, unique_id_in_definition: -1, }); diff --git a/src/protocol/parser/pass_stack_size.rs b/src/protocol/parser/pass_stack_size.rs index 60e5ba5a2369557292c59b2c16935e9ee80cc315..55acf4961cab58a23cf0d9be3fdf185e2be50951 100644 --- a/src/protocol/parser/pass_stack_size.rs +++ b/src/protocol/parser/pass_stack_size.rs @@ -43,20 +43,12 @@ impl Visitor for PassStackSize { return Ok(()) } - fn visit_function_definition(&mut self, ctx: &mut Ctx, id: FunctionDefinitionId) -> VisitorResult { + fn visit_procedure_definition(&mut self, ctx: &mut Ctx, id: ProcedureDefinitionId) -> VisitorResult { let definition = &ctx.heap[id]; let scope_id = definition.scope; self.visit_scope_and_assign_local_ids(ctx, scope_id, 0); - return Ok(()) - } - - fn visit_component_definition(&mut self, ctx: &mut Ctx, id: ComponentDefinitionId) -> VisitorResult { - let definition = &ctx.heap[id]; - let scope_id = definition.scope; - - self.visit_scope_and_assign_local_ids(ctx, scope_id, 0); - return Ok(()) + return Ok(()); } } diff --git a/src/protocol/parser/pass_symbols.rs b/src/protocol/parser/pass_symbols.rs index 9f48caf8d41d83e2506044c5e009aeb63794dd96..995dfa15100c3f0d1e3f44779257ea150cbeb60e 100644 --- a/src/protocol/parser/pass_symbols.rs +++ b/src/protocol/parser/pass_symbols.rs @@ -230,23 +230,23 @@ impl PassSymbols { ast_definition_id = union_def_id.upcast() }, KW_FUNCTION => { - let func_def_id = ctx.heap.alloc_function_definition(|this| { - FunctionDefinition::new_empty(this, module.root_id, definition_span, identifier, poly_vars) + let proc_def_id = ctx.heap.alloc_procedure_definition(|this| { + ProcedureDefinition::new_empty(this, module.root_id, definition_span, ProcedureKind::Function, identifier, poly_vars) }); definition_class = DefinitionClass::Function; - ast_definition_id = func_def_id.upcast(); + ast_definition_id = proc_def_id.upcast(); }, KW_PRIMITIVE | KW_COMPOSITE => { - let component_variant = if kw_text == KW_PRIMITIVE { - ComponentVariant::Primitive + let procedure_kind = if kw_text == KW_PRIMITIVE { + ProcedureKind::Primitive } else { - ComponentVariant::Composite + ProcedureKind::Composite }; - let comp_def_id = ctx.heap.alloc_component_definition(|this| { - ComponentDefinition::new_empty(this, module.root_id, definition_span, component_variant, identifier, poly_vars) + let proc_def_id = ctx.heap.alloc_procedure_definition(|this| { + ProcedureDefinition::new_empty(this, module.root_id, definition_span, procedure_kind, identifier, poly_vars) }); definition_class = DefinitionClass::Component; - ast_definition_id = comp_def_id.upcast(); + ast_definition_id = proc_def_id.upcast(); }, _ => unreachable!("encountered keyword '{}' in definition range", String::from_utf8_lossy(kw_text)), } diff --git a/src/protocol/parser/pass_typing.rs b/src/protocol/parser/pass_typing.rs index 225f8c22c1a2eef4117c1da4051ea3391a17f1dd..3986dc01dc01c708ef54ca8b842dc8d7ef17c998 100644 --- a/src/protocol/parser/pass_typing.rs +++ b/src/protocol/parser/pass_typing.rs @@ -810,20 +810,6 @@ type InferNodeIndex = usize; type PolyDataIndex = isize; type VarDataIndex = usize; -enum DefinitionType{ - Component(ComponentDefinitionId), - Function(FunctionDefinitionId), -} - -impl DefinitionType { - fn definition_id(&self) -> DefinitionId { - match self { - DefinitionType::Component(v) => v.upcast(), - DefinitionType::Function(v) => v.upcast(), - } - } -} - pub(crate) struct ResolveQueueElement { // Note that using the `definition_id` and the `monomorph_idx` one may // query the type table for the full procedure type, thereby retrieving @@ -1014,7 +1000,8 @@ struct InferenceRuleVariableExpr { pub(crate) struct PassTyping { // Current definition we're typechecking. reserved_type_id: TypeId, - definition_type: DefinitionType, + procedure_id: ProcedureDefinitionId, + procedure_kind: ProcedureKind, poly_vars: Vec, // Temporary variables during construction of inference rulesr parent_index: Option, @@ -1092,7 +1079,8 @@ impl PassTyping { pub(crate) fn new() -> Self { PassTyping { reserved_type_id: TypeId::new_invalid(), - definition_type: DefinitionType::Function(FunctionDefinitionId::new_invalid()), + procedure_id: ProcedureDefinitionId::new_invalid(), + procedure_kind: ProcedureKind::Function, poly_vars: Vec::new(), parent_index: None, var_buffer: ScopedBuffer::with_capacity(BUFFER_INIT_CAP_LARGE), @@ -1116,20 +1104,17 @@ impl PassTyping { let definition = &ctx.heap[*definition_id]; let first_concrete_part = match definition { - Definition::Function(definition) => { + Definition::Procedure(definition) => { if definition.poly_vars.is_empty() { - Some(ConcreteTypePart::Function(*definition_id, 0)) + if definition.kind == ProcedureKind::Function { + Some(ConcreteTypePart::Function(definition.this, 0)) + } else { + Some(ConcreteTypePart::Component(definition.this, 0)) + } } else { None } } - Definition::Component(definition) => { - if definition.poly_vars.is_empty() { - Some(ConcreteTypePart::Component(*definition_id, 0)) - } else { - None - } - }, Definition::Enum(_) | Definition::Struct(_) | Definition::Union(_) => None, }; @@ -1172,7 +1157,8 @@ impl PassTyping { fn reset(&mut self) { self.reserved_type_id = TypeId::new_invalid(); - self.definition_type = DefinitionType::Function(FunctionDefinitionId::new_invalid()); + self.procedure_id = ProcedureDefinitionId::new_invalid(); + self.procedure_kind = ProcedureKind::Function; self.poly_vars.clear(); self.parent_index = None; @@ -1201,60 +1187,19 @@ impl PassTyping { fn visit_struct_definition(&mut self, _: &mut Ctx, _: StructDefinitionId) -> VisitorResult { return Ok(()) } fn visit_union_definition(&mut self, _: &mut Ctx, _: UnionDefinitionId) -> VisitorResult { return Ok(()) } - fn visit_component_definition(&mut self, ctx: &mut Ctx, id: ComponentDefinitionId) -> VisitorResult { - self.definition_type = DefinitionType::Component(id); - - let comp_def = &ctx.heap[id]; - debug_assert_eq!(comp_def.poly_vars.len(), self.poly_vars.len(), "component polyvars do not match imposed polyvars"); - - debug_log!("{}", "-".repeat(50)); - debug_log!("Visiting component '{}': {}", comp_def.identifier.value.as_str(), id.0.index); - debug_log!("{}", "-".repeat(50)); - - // Visit parameters - let section = self.var_buffer.start_section_initialized(comp_def.parameters.as_slice()); - for param_id in section.iter_copied() { - let param = &ctx.heap[param_id]; - let var_type = self.determine_inference_type_from_parser_type_elements(¶m.parser_type.elements, true); - debug_assert!(var_type.is_done, "expected component arguments to be concrete types"); - self.var_data.push(VarData{ - var_id: param_id, - var_type, - used_at: Vec::new(), - linked_var: None - }); - } - section.forget(); - - // Visit the body and all of its expressions - let body_stmt_id = ctx.heap[id].body; - self.parent_index = None; - self.visit_block_stmt(ctx, body_stmt_id) - } - - fn visit_function_definition(&mut self, ctx: &mut Ctx, id: FunctionDefinitionId) -> VisitorResult { - self.definition_type = DefinitionType::Function(id); + fn visit_procedure_definition(&mut self, ctx: &mut Ctx, id: ProcedureDefinitionId) -> VisitorResult { + let procedure_def = &ctx.heap[id]; - let func_def = &ctx.heap[id]; - debug_assert_eq!(func_def.poly_vars.len(), self.poly_vars.len(), "function polyvars do not match imposed polyvars"); + self.procedure_id = id; + self.procedure_kind = procedure_def.kind; + let body_id = procedure_def.body; debug_log!("{}", "-".repeat(50)); - debug_log!("Visiting function '{}': {}", func_def.identifier.value.as_str(), id.0.index); - if debug_log_enabled!() { - debug_log!("Polymorphic variables:"); - for (_idx, poly_var) in self.poly_vars.iter().enumerate() { - let mut infer_type_parts = Vec::new(); - Self::determine_inference_type_from_concrete_type( - &mut infer_type_parts, &poly_var.parts - ); - let _infer_type = InferenceType::new(false, true, infer_type_parts); - debug_log!(" - [{:03}] {:?}", _idx, _infer_type.display_name(&ctx.heap)); - } - } + debug_log!("Visiting procedure: '{}' (id: {}, kind: {:?})", procedure_def.identifier.value.as_str(), id.0.index, procedure_def.kind); debug_log!("{}", "-".repeat(50)); // Visit parameters - let section = self.var_buffer.start_section_initialized(func_def.parameters.as_slice()); + let section = self.var_buffer.start_section_initialized(procedure_def.parameters.as_slice()); for param_id in section.iter_copied() { let param = &ctx.heap[param_id]; let var_type = self.determine_inference_type_from_parser_type_elements(¶m.parser_type.elements, true); @@ -1269,9 +1214,8 @@ impl PassTyping { section.forget(); // Visit all of the expressions within the body - let body_stmt_id = ctx.heap[id].body; self.parent_index = None; - self.visit_block_stmt(ctx, body_stmt_id) + return self.visit_block_stmt(ctx, body_id); } // Statements @@ -2021,7 +1965,7 @@ impl PassTyping { if !poly_type.is_done { let expr = &ctx.heap[expr_id]; let definition = match expr { - Expression::Call(expr) => expr.definition, + Expression::Call(expr) => expr.procedure.upcast(), Expression::Literal(expr) => match &expr.value { Literal::Enum(lit) => lit.definition, Literal::Union(lit) => lit.definition, @@ -2072,16 +2016,16 @@ impl PassTyping { Expression::Call(expr) => { // Check if it is not a builtin function. If not, then // construct the first part of the concrete type. - let first_concrete_part = if expr.method == Method::UserFunction { - ConcreteTypePart::Function(expr.definition, poly_data.poly_vars.len() as u32) + let first_concrete_part = if expr.method == Method::UserProcedure { + ConcreteTypePart::Function(expr.procedure, poly_data.poly_vars.len() as u32) } else if expr.method == Method::UserComponent { - ConcreteTypePart::Component(expr.definition, poly_data.poly_vars.len() as u32) + ConcreteTypePart::Component(expr.procedure, poly_data.poly_vars.len() as u32) } else { // Builtin function continue; }; - let definition_id = expr.definition; + let definition_id = expr.procedure.upcast(); let concrete_type = inference_type_to_concrete_type( ctx, infer_expr.expr_id, &poly_data.poly_vars, first_concrete_part )?; @@ -2128,16 +2072,7 @@ impl PassTyping { // Every expression checked, and new monomorphs are queued. Transfer the // expression information to the type table. - let procedure_arguments = match &self.definition_type { - DefinitionType::Component(id) => { - let definition = &ctx.heap[*id]; - &definition.parameters - }, - DefinitionType::Function(id) => { - let definition = &ctx.heap[*id]; - &definition.parameters - }, - }; + let procedure_arguments = &ctx.heap[self.procedure_id].parameters; let target = ctx.types.get_procedure_monomorph_mut(self.reserved_type_id); debug_assert!(target.arg_types.is_empty()); // makes sure we never queue a procedure's type inferencing twice @@ -3022,7 +2957,10 @@ impl PassTyping { while part_index < expr_type.parts.len() { let part = &expr_type.parts[part_index]; - if part.is_marker() { continue; } + if part.is_marker() { + part_index += 1; + continue; + } if !part.is_concrete() { break; } if *part == InferenceTypePart::String { @@ -3218,7 +3156,7 @@ impl PassTyping { /// type, then we should also progress the associated expression, hence the /// `associated_node_index`. fn apply_polydata_polyvar_constraint( - &mut self, ctx: &Ctx, + &mut self, _ctx: &Ctx, outer_node_index: InferNodeIndex, poly_data_type_index: PolyDataTypeIndex, associated_node_index: InferNodeIndex, poly_progress_section: &ScopedSection ) -> bool { @@ -3441,16 +3379,12 @@ impl PassTyping { EP::If(_) | EP::While(_) => // Must be a boolean InferenceType::new(false, true, vec![ITP::Bool]), - EP::Return(_) => + EP::Return(_) => { // Must match the return type of the function - if let DefinitionType::Function(func_id) = self.definition_type { - let returned = &ctx.heap[func_id].return_type; - self.determine_inference_type_from_parser_type_elements(&returned.elements, true) - } else { - // Cannot happen: definition always set upon body traversal - // and "return" calls in components are illegal. - unreachable!(); - }, + debug_assert_eq!(self.procedure_kind, ProcedureKind::Function); + let returned = &ctx.heap[self.procedure_id].return_type.as_ref().unwrap(); + self.determine_inference_type_from_parser_type_elements(&returned.elements, true) + }, EP::New(_) => // Must be a component call, which we assign a "Void" return // type @@ -3493,33 +3427,25 @@ impl PassTyping { } // Handle the arguments and return types - let definition = &ctx.heap[call.definition]; - let (parameters, returned) = match definition { - Definition::Component(definition) => { - debug_assert_eq!(poly_args.len(), definition.poly_vars.len()); - (&definition.parameters, None) - }, - Definition::Function(definition) => { - debug_assert_eq!(poly_args.len(), definition.poly_vars.len()); - (&definition.parameters, Some(&definition.return_type)) - }, - Definition::Struct(_) | Definition::Enum(_) | Definition::Union(_) => { - unreachable!("insert_initial_call_polymorph data for non-procedure type"); - }, - }; + let definition = &ctx.heap[call.procedure]; + debug_assert_eq!(poly_args.len(), definition.poly_vars.len()); - let mut parameter_types = Vec::with_capacity(parameters.len()); - for parameter_id in parameters.clone().into_iter() { // TODO: @Performance @Now + let mut parameter_types = Vec::with_capacity(definition.parameters.len()); + let parameter_section = self.var_buffer.start_section_initialized(&definition.parameters); + for parameter_id in parameter_section.iter_copied() { let param = &ctx.heap[parameter_id]; parameter_types.push(self.determine_inference_type_from_parser_type_elements(¶m.parser_type.elements, false)); } + parameter_section.forget(); - let return_type = match returned { + let return_type = match &definition.return_type { None => { // Component, so returns a "Void" + debug_assert_ne!(definition.kind, ProcedureKind::Function); InferenceType::new(false, true, vec![InferenceTypePart::Void]) }, Some(returned) => { + debug_assert_eq!(definition.kind, ProcedureKind::Function); self.determine_inference_type_from_parser_type_elements(&returned.elements, false) } }; @@ -3527,7 +3453,7 @@ impl PassTyping { let extra_data_idx = self.poly_data.len() as PolyDataIndex; self.poly_data.push(PolyData { first_rule_application: true, - definition_id: call.definition, + definition_id: call.procedure.upcast(), poly_vars: poly_args, expr_types: PolyDataTypes { associated: parameter_types, @@ -3825,7 +3751,7 @@ impl PassTyping { if use_definitions_known_poly_args { // Refers to polymorphic argument on procedure we're currently processing. // This argument is already known. - debug_assert_eq!(*belongs_to_definition, self.definition_type.definition_id()); + debug_assert_eq!(*belongs_to_definition, self.procedure_id.upcast()); debug_assert!((poly_arg_idx as usize) < self.poly_vars.len()); Self::determine_inference_type_from_concrete_type( diff --git a/src/protocol/parser/pass_validation_linking.rs b/src/protocol/parser/pass_validation_linking.rs index 30bd3bb11139bc5d185f8c7effa239adc70fbd65..e810ad3b936071042027a5b2409a30d75b7775fe 100644 --- a/src/protocol/parser/pass_validation_linking.rs +++ b/src/protocol/parser/pass_validation_linking.rs @@ -50,26 +50,6 @@ use super::visitor::{ }; use crate::protocol::parser::ModuleCompilationPhase; -#[derive(PartialEq, Eq)] -enum DefinitionType { - Primitive(ComponentDefinitionId), - Composite(ComponentDefinitionId), - Function(FunctionDefinitionId) -} - -impl DefinitionType { - fn is_primitive(&self) -> bool { if let Self::Primitive(_) = self { true } else { false } } - fn is_composite(&self) -> bool { if let Self::Composite(_) = self { true } else { false } } - fn is_function(&self) -> bool { if let Self::Function(_) = self { true } else { false } } - fn definition_id(&self) -> DefinitionId { - match self { - DefinitionType::Primitive(v) => v.upcast(), - DefinitionType::Composite(v) => v.upcast(), - DefinitionType::Function(v) => v.upcast(), - } - } -} - struct ControlFlowStatement { in_sync: SynchronousStatementId, in_while: WhileStatementId, @@ -103,7 +83,8 @@ pub(crate) struct PassValidationLinking { // Traversal state, current scope (which can be used to find the parent // scope) and the definition variant we are considering. cur_scope: ScopeId, - def_type: DefinitionType, + proc_id: ProcedureDefinitionId, + proc_kind: ProcedureKind, // "Trailing" traversal state, set be child/prev stmt/expr used by next one prev_stmt: StatementId, expr_parent: ExpressionParent, @@ -139,7 +120,8 @@ impl PassValidationLinking { cur_scope: ScopeId::new_invalid(), prev_stmt: StatementId::new_invalid(), expr_parent: ExpressionParent::None, - def_type: DefinitionType::Function(FunctionDefinitionId::new_invalid()), + proc_id: ProcedureDefinitionId::new_invalid(), + proc_kind: ProcedureKind::Function, must_be_assignable: None, relative_pos_in_parent: 0, next_expr_index: 0, @@ -160,7 +142,8 @@ impl PassValidationLinking { self.in_binding_expr = BindingExpressionId::new_invalid(); self.in_binding_expr_lhs = false; self.cur_scope = ScopeId::new_invalid(); - self.def_type = DefinitionType::Function(FunctionDefinitionId::new_invalid()); + self.proc_id = ProcedureDefinitionId::new_invalid(); + self.proc_kind = ProcedureKind::Function; self.prev_stmt = StatementId::new_invalid(); self.expr_parent = ExpressionParent::None; self.must_be_assignable = None; @@ -206,56 +189,17 @@ impl Visitor for PassValidationLinking { // Definition visitors //-------------------------------------------------------------------------- - fn visit_component_definition(&mut self, ctx: &mut Ctx, id: ComponentDefinitionId) -> VisitorResult { + fn visit_procedure_definition(&mut self, ctx: &mut Ctx, id: ProcedureDefinitionId) -> VisitorResult { self.reset_state(); let definition = &ctx.heap[id]; - self.def_type = match &definition.variant { - ComponentVariant::Primitive => DefinitionType::Primitive(id), - ComponentVariant::Composite => DefinitionType::Composite(id), - }; - self.expr_parent = ExpressionParent::None; - - // Visit parameters and assign a unique scope ID - let definition_scope_id = definition.scope; - let old_scope = self.push_scope(ctx, true, definition_scope_id); - - let definition = &ctx.heap[id]; - let body_id = definition.body; - let section = self.variable_buffer.start_section_initialized(&definition.parameters); - for variable_idx in 0..section.len() { - let variable_id = section[variable_idx]; - self.checked_at_single_scope_add_local(ctx, self.cur_scope, -1, variable_id)?; - } - self.relative_pos_in_parent = section.len() as i32; - - section.forget(); - - // Visit statements in component body - self.visit_block_stmt(ctx, body_id)?; - self.pop_scope(old_scope); - - // Assign total number of expressions and assign an in-block unique ID - // to each of the locals in the procedure. - let definition = &mut ctx.heap[id]; - definition.num_expressions_in_body = self.next_expr_index; - - self.resolve_pending_control_flow_targets(ctx)?; - - Ok(()) - } - - fn visit_function_definition(&mut self, ctx: &mut Ctx, id: FunctionDefinitionId) -> VisitorResult { - self.reset_state(); - - // Set internal statement indices - self.def_type = DefinitionType::Function(id); + self.proc_id = id; + self.proc_kind = definition.kind; self.expr_parent = ExpressionParent::None; - // Visit parameters and assign a unique scope ID - let definition = &ctx.heap[id]; - let definition_scope_id = definition.scope; - let old_scope = self.push_scope(ctx, true, definition_scope_id); + // Visit parameters + let scope_id = definition.scope; + let old_scope = self.push_scope(ctx, true, scope_id); let definition = &ctx.heap[id]; let body_id = definition.body; @@ -460,7 +404,7 @@ impl Visitor for PassValidationLinking { )); } - if !self.def_type.is_primitive() { + if self.proc_kind != ProcedureKind::Primitive { return Err(ParseError::new_error_str_at_span( &ctx.module().source, cur_sync_span, "synchronous statements may only be used in primitive components" @@ -532,7 +476,7 @@ impl Visitor for PassValidationLinking { )); } - if !self.def_type.is_primitive() { + if self.proc_kind != ProcedureKind::Primitive { return Err(ParseError::new_error_str_at_span( &ctx.module().source, select_stmt.span, "select statements may only be used in primitive components" @@ -587,7 +531,7 @@ impl Visitor for PassValidationLinking { fn visit_return_stmt(&mut self, ctx: &mut Ctx, id: ReturnStatementId) -> VisitorResult { // Check if "return" occurs within a function let stmt = &ctx.heap[id]; - if !self.def_type.is_function() { + if self.proc_kind != ProcedureKind::Function { return Err(ParseError::new_error_str_at_span( &ctx.module().source, stmt.span, "return statements may only appear in function bodies" @@ -619,7 +563,7 @@ impl Visitor for PassValidationLinking { fn visit_new_stmt(&mut self, ctx: &mut Ctx, id: NewStatementId) -> VisitorResult { // Make sure the new statement occurs inside a composite component - if !self.def_type.is_composite() { + if self.proc_kind != ProcedureKind::Composite { let new_stmt = &ctx.heap[id]; return Err(ParseError::new_error_str_at_span( &ctx.module().source, new_stmt.span, @@ -1228,7 +1172,7 @@ impl Visitor for PassValidationLinking { Method::Assert => { expecting_wrapping_sync_stmt = true; expecting_no_select_stmt = true; - if self.def_type.is_function() { + if self.proc_kind == ProcedureKind::Function { let call_span = call_expr.func_span; return Err(ParseError::new_error_str_at_span( &ctx.module().source, call_span, @@ -1240,7 +1184,7 @@ impl Visitor for PassValidationLinking { Method::SelectStart | Method::SelectRegisterCasePort | Method::SelectWait => unreachable!(), // not usable by programmer directly - Method::UserFunction => {}, + Method::UserProcedure => {} Method::UserComponent => { expecting_wrapping_new_stmt = true; }, @@ -1255,7 +1199,7 @@ impl Visitor for PassValidationLinking { return (span, name); } if expecting_primitive_def { - if !self.def_type.is_primitive() { + if self.proc_kind != ProcedureKind::Primitive { let (call_span, func_name) = get_span_and_name(ctx, id); return Err(ParseError::new_error_at_span( &ctx.module().source, call_span, @@ -1303,11 +1247,10 @@ impl Visitor for PassValidationLinking { } // Check the number of arguments - let call_definition = ctx.types.get_base_definition(&call_expr.definition).unwrap(); + let call_definition = ctx.types.get_base_definition(&call_expr.procedure.upcast()).unwrap(); let num_expected_args = match &call_definition.definition { - DefinedTypeVariant::Function(definition) => definition.arguments.len(), - DefinedTypeVariant::Component(definition) => definition.arguments.len(), - v => unreachable!("encountered {} type in call expression", v.type_class()), + DefinedTypeVariant::Procedure(definition) => definition.arguments.len(), + _ => unreachable!(), }; let num_provided_args = call_expr.arguments.len(); @@ -1595,7 +1538,7 @@ impl PassValidationLinking { ) -> Result<(), ParseError> { // Check the symbol table for conflicts { - let cur_scope = SymbolScope::Definition(self.def_type.definition_id()); + let cur_scope = SymbolScope::Definition(self.proc_id.upcast()); let ident = &ctx.heap[new_variable_id].identifier; if let Some(symbol) = ctx.symbols.get_symbol_by_name(cur_scope, &ident.value.as_bytes()) { return Err(ParseError::new_error_str_at_span( diff --git a/src/protocol/parser/type_table.rs b/src/protocol/parser/type_table.rs index 6279724617adbc3d434ce60f61653038ff177f6e..24c7dafe70fa6df85b069b86e64321caba4c2469 100644 --- a/src/protocol/parser/type_table.rs +++ b/src/protocol/parser/type_table.rs @@ -36,7 +36,6 @@ * layout. */ -use std::fmt::{Formatter, Result as FmtResult}; use std::collections::HashMap; use std::hash::{Hash, Hasher}; @@ -49,40 +48,6 @@ use crate::protocol::parser::*; // Defined Types //------------------------------------------------------------------------------ -#[derive(Copy, Clone, PartialEq, Eq)] -pub enum TypeClass { - Enum, - Union, - Struct, - Function, - Component -} - -impl TypeClass { - pub(crate) fn display_name(&self) -> &'static str { - match self { - TypeClass::Enum => "enum", - TypeClass::Union => "union", - TypeClass::Struct => "struct", - TypeClass::Function => "function", - TypeClass::Component => "component", - } - } - - pub(crate) fn is_data_type(&self) -> bool { - match self { - TypeClass::Enum | TypeClass::Union | TypeClass::Struct => true, - TypeClass::Function | TypeClass::Component => false, - } - } -} - -impl std::fmt::Display for TypeClass { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!(f, "{}", self.display_name()) - } -} - /// Struct wrapping around a potentially polymorphic type. If the type does not /// have any polymorphic arguments then it will not have any monomorphs and /// `is_polymorph` will be set to `false`. A type with polymorphic arguments @@ -102,39 +67,37 @@ pub enum DefinedTypeVariant { Enum(EnumType), Union(UnionType), Struct(StructType), - Function(FunctionType), - Component(ComponentType) + Procedure(ProcedureType), } impl DefinedTypeVariant { - pub(crate) fn type_class(&self) -> TypeClass { + pub(crate) fn is_data_type(&self) -> bool { + use DefinedTypeVariant as DTV; + match self { - DefinedTypeVariant::Enum(_) => TypeClass::Enum, - DefinedTypeVariant::Union(_) => TypeClass::Union, - DefinedTypeVariant::Struct(_) => TypeClass::Struct, - DefinedTypeVariant::Function(_) => TypeClass::Function, - DefinedTypeVariant::Component(_) => TypeClass::Component + DTV::Struct(_) | DTV::Enum(_) | DTV::Union(_) => return true, + DTV::Procedure(_) => return false, } } pub(crate) fn as_struct(&self) -> &StructType { match self { DefinedTypeVariant::Struct(v) => v, - _ => unreachable!("Cannot convert {} to struct variant", self.type_class()) + _ => unreachable!() } } pub(crate) fn as_enum(&self) -> &EnumType { match self { DefinedTypeVariant::Enum(v) => v, - _ => unreachable!("Cannot convert {} to enum variant", self.type_class()) + _ => unreachable!() } } pub(crate) fn as_union(&self) -> &UnionType { match self { DefinedTypeVariant::Union(v) => v, - _ => unreachable!("Cannot convert {} to union variant", self.type_class()) + _ => unreachable!() } } } @@ -197,19 +160,14 @@ pub struct StructField { pub parser_type: ParserType, } -/// `FunctionType` is what you expect it to be: a particular function's -/// signature. -pub struct FunctionType { - pub return_type: ParserType, - pub arguments: Vec, -} - -pub struct ComponentType { - pub variant: ComponentVariant, - pub arguments: Vec, +/// `ProcedureType` is the signature of a procedure/component +pub struct ProcedureType { + pub kind: ProcedureKind, + pub return_type: Option, + pub arguments: Vec, } -pub struct FunctionArgument { +pub struct ProcedureArgument { identifier: Identifier, parser_type: ParserType, } @@ -674,8 +632,7 @@ impl TypeTable { Definition::Enum(_) => self.build_base_enum_definition(modules, ctx, definition_id)?, Definition::Union(_) => self.build_base_union_definition(modules, ctx, definition_id)?, Definition::Struct(_) => self.build_base_struct_definition(modules, ctx, definition_id)?, - Definition::Function(_) => self.build_base_function_definition(modules, ctx, definition_id)?, - Definition::Component(_) => self.build_base_component_definition(modules, ctx, definition_id)?, + Definition::Procedure(_) => self.build_base_procedure_definition(modules, ctx, definition_id)?, } } @@ -691,7 +648,7 @@ impl TypeTable { let definition_id = ctx.heap.definitions.get_id(definition_idx); let poly_type = self.definition_lookup.get(&definition_id).unwrap(); - if !poly_type.definition.type_class().is_data_type() || !poly_type.poly_vars.is_empty() { + if !poly_type.definition.is_data_type() || !poly_type.poly_vars.is_empty() { continue; } @@ -1000,73 +957,27 @@ impl TypeTable { return Ok(()) } - /// Builds base function type. - fn build_base_function_definition(&mut self, modules: &[Module], ctx: &mut PassCtx, definition_id: DefinitionId) -> Result<(), ParseError> { + /// Builds base procedure type. + fn build_base_procedure_definition(&mut self, modules: &[Module], ctx: &mut PassCtx, definition_id: DefinitionId) -> Result<(), ParseError> { debug_assert!(!self.definition_lookup.contains_key(&definition_id), "base function already built"); - let definition = ctx.heap[definition_id].as_function(); + let definition = ctx.heap[definition_id].as_procedure(); let root_id = definition.defined_in; // Check and construct return types and argument types. - Self::check_member_parser_type( - modules, ctx, root_id, &definition.return_type, definition.builtin - )?; - - let mut arguments = Vec::with_capacity(definition.parameters.len()); - for parameter_id in &definition.parameters { - let parameter = &ctx.heap[*parameter_id]; + if let Some(return_type) = &definition.return_type { Self::check_member_parser_type( - modules, ctx, root_id, ¶meter.parser_type, definition.builtin + modules, ctx, root_id, return_type, definition.builtin )?; - - arguments.push(FunctionArgument{ - identifier: parameter.identifier.clone(), - parser_type: parameter.parser_type.clone(), - }); } - // Check conflict of identifiers - Self::check_identifier_collision( - modules, root_id, &arguments, |arg| &arg.identifier, "function argument" - )?; - Self::check_poly_args_collision(modules, ctx, root_id, &definition.poly_vars)?; - - // Construct internal representation of function type - let mut poly_vars = Self::create_polymorphic_variables(&definition.poly_vars); - - Self::mark_used_polymorphic_variables(&mut poly_vars, &definition.return_type); - for argument in &arguments { - Self::mark_used_polymorphic_variables(&mut poly_vars, &argument.parser_type); - } - - let is_polymorph = poly_vars.iter().any(|arg| arg.is_in_use); - - self.definition_lookup.insert(definition_id, DefinedType{ - ast_root: root_id, - ast_definition: definition_id, - definition: DefinedTypeVariant::Function(FunctionType{ return_type: definition.return_type.clone(), arguments }), - poly_vars, - is_polymorph - }); - - return Ok(()); - } - - /// Builds base component type. - fn build_base_component_definition(&mut self, modules: &[Module], ctx: &mut PassCtx, definition_id: DefinitionId) -> Result<(), ParseError> { - debug_assert!(!self.definition_lookup.contains_key(&definition_id), "base component already built"); - - let definition = &ctx.heap[definition_id].as_component(); - let root_id = definition.defined_in; - - // Check the argument types let mut arguments = Vec::with_capacity(definition.parameters.len()); for parameter_id in &definition.parameters { let parameter = &ctx.heap[*parameter_id]; Self::check_member_parser_type( - modules, ctx, root_id, ¶meter.parser_type, false + modules, ctx, root_id, ¶meter.parser_type, definition.builtin )?; - arguments.push(FunctionArgument{ + arguments.push(ProcedureArgument{ identifier: parameter.identifier.clone(), parser_type: parameter.parser_type.clone(), }); @@ -1074,18 +985,17 @@ impl TypeTable { // Check conflict of identifiers Self::check_identifier_collision( - modules, root_id, &arguments, |arg| &arg.identifier, "connector argument" + modules, root_id, &arguments, |arg| &arg.identifier, "procedure argument" )?; Self::check_poly_args_collision(modules, ctx, root_id, &definition.poly_vars)?; - // Construct internal representation of component - // TODO: Marking used polymorphic variables on procedures requires - // making sure that each is used in the body. For now, mark them all - // as required. + // Construct internal representation of function type + // TODO: Marking used polymorphic variables should take statements in + // the body into account. But currently we don't. Hence mark them all + // as being in-use. Note to self: true condition should be that the + // polymorphic variables are used in places where the resulting types + // are themselves truly polymorphic types (e.g. not a phantom type). let mut poly_vars = Self::create_polymorphic_variables(&definition.poly_vars); - // for argument in &arguments { - // Self::mark_used_polymorphic_variables(&mut poly_vars, &argument.parser_type); - // } for poly_var in &mut poly_vars { poly_var.is_in_use = true; } @@ -1095,12 +1005,16 @@ impl TypeTable { self.definition_lookup.insert(definition_id, DefinedType{ ast_root: root_id, ast_definition: definition_id, - definition: DefinedTypeVariant::Component(ComponentType{ variant: definition.variant, arguments }), + definition: DefinedTypeVariant::Procedure(ProcedureType{ + kind: definition.kind, + return_type: definition.return_type.clone(), + arguments + }), poly_vars, is_polymorph }); - Ok(()) + return Ok(()); } /// Will check if the member type (field of a struct, embedded type in a @@ -1550,15 +1464,17 @@ impl TypeTable { let type_id = mono_type_map.get(&mono_key).copied(); (DefinitionId::new_invalid(), type_id) }, - CTP::Instance(definition_id, _) | - CTP::Function(definition_id, _) | - CTP::Component(definition_id, _) => { + CTP::Instance(definition_id, _) => { let definition_type = definition_map.get(definition_id).unwrap(); mono_key.set(&concrete_type.parts, &definition_type.poly_vars); let type_id = mono_type_map.get(&mono_key).copied(); (*definition_id, type_id) }, + CTP::Function(_, _) | + CTP::Component(_, _) => { + todo!("function pointers") + }, _ => { return TypeLoopResult::TypeExists }, @@ -1689,7 +1605,7 @@ impl TypeTable { type_id }, - DTV::Function(_) | DTV::Component(_) => { + DTV::Procedure(_) => { unreachable!("pushing type resolving breadcrumb for procedure type") }, }; @@ -2265,10 +2181,12 @@ fn align_offset_to(offset: &mut usize, alignment: usize) { #[inline] fn get_concrete_type_definition(concrete_parts: &[ConcreteTypePart]) -> Option { match concrete_parts[0] { - ConcreteTypePart::Instance(definition_id, _) | + ConcreteTypePart::Instance(definition_id, _) => { + return Some(definition_id) + }, ConcreteTypePart::Function(definition_id, _) | ConcreteTypePart::Component(definition_id, _) => { - return Some(definition_id); + return Some(definition_id.upcast()); }, _ => { return None; diff --git a/src/protocol/parser/visitor.rs b/src/protocol/parser/visitor.rs index a94fb28b94113846eb558566b6bcc7b35f5c958b..8bf927f563aeb8a2819f703c87477c4db8d60fb4 100644 --- a/src/protocol/parser/visitor.rs +++ b/src/protocol/parser/visitor.rs @@ -137,13 +137,9 @@ macro_rules! visitor_recursive_definition_impl { let def = def.this; $this.visit_struct_definition($ctx, def) }, - Definition::Component(def) => { + Definition::Procedure(def) => { let def = def.this; - $this.visit_component_definition($ctx, def) - }, - Definition::Function(def) => { - let def = def.this; - $this.visit_function_definition($ctx, def) + $this.visit_procedure_definition($ctx, def) }, } } @@ -238,8 +234,7 @@ pub(crate) trait Visitor { fn visit_enum_definition(&mut self, _ctx: &mut Ctx, _id: EnumDefinitionId) -> VisitorResult { Ok(()) } fn visit_union_definition(&mut self, _ctx: &mut Ctx, _id: UnionDefinitionId) -> VisitorResult{ Ok(()) } fn visit_struct_definition(&mut self, _ctx: &mut Ctx, _id: StructDefinitionId) -> VisitorResult { Ok(()) } - fn visit_component_definition(&mut self, _ctx: &mut Ctx, _id: ComponentDefinitionId) -> VisitorResult { Ok(()) } - fn visit_function_definition(&mut self, _ctx: &mut Ctx, _id: FunctionDefinitionId) -> VisitorResult { Ok(()) } + fn visit_procedure_definition(&mut self, _ctx: &mut Ctx, _id: ProcedureDefinitionId) -> VisitorResult { Ok(()) } // Statements // --- enum matching diff --git a/src/protocol/tests/utils.rs b/src/protocol/tests/utils.rs index d599014400b8b193e8bded700bdcba2fdfeafb65..802e5625a6ccb1640a5a36cea919568fada4d3d7 100644 --- a/src/protocol/tests/utils.rs +++ b/src/protocol/tests/utils.rs @@ -218,7 +218,7 @@ impl AstOkTester { pub(crate) fn for_function(self, name: &str, f: F) -> Self { let mut found = false; for definition in self.heap.definitions.iter() { - if let Definition::Function(definition) = definition { + if let Definition::Procedure(definition) = definition { if definition.identifier.value.as_str() != name { continue; } @@ -507,11 +507,11 @@ impl<'a> UnionTester<'a> { pub(crate) struct FunctionTester<'a> { ctx: TestCtx<'a>, - def: &'a FunctionDefinition, + def: &'a ProcedureDefinition, } impl<'a> FunctionTester<'a> { - fn new(ctx: TestCtx<'a>, def: &'a FunctionDefinition) -> Self { + fn new(ctx: TestCtx<'a>, def: &'a ProcedureDefinition) -> Self { Self{ ctx, def } } @@ -700,11 +700,11 @@ impl<'a> FunctionTester<'a> { use crate::protocol::*; // Assuming the function is not polymorphic - let definition_id = self.def.this.upcast(); + let definition_id = self.def.this; let func_type = [ConcreteTypePart::Function(definition_id, 0)]; - let mono_index = self.ctx.types.get_procedure_monomorph_type_id(&definition_id, &func_type).unwrap(); + let mono_index = self.ctx.types.get_procedure_monomorph_type_id(&definition_id.upcast(), &func_type).unwrap(); - let mut prompt = Prompt::new(&self.ctx.types, &self.ctx.heap, self.def.this.upcast(), mono_index, ValueGroup::new_stack(Vec::new())); + let mut prompt = Prompt::new(&self.ctx.types, &self.ctx.heap, definition_id, mono_index, ValueGroup::new_stack(Vec::new())); let mut call_context = FakeRunContext{}; loop { let result = prompt.step(&self.ctx.types, &self.ctx.heap, &self.ctx.modules, &mut call_context); @@ -806,14 +806,11 @@ impl<'a> ExpressionTester<'a> { } fn get_procedure_monomorph<'a>(heap: &Heap, types: &'a TypeTable, definition_id: DefinitionId) -> &'a ProcedureMonomorph { - let ast_definition = &heap[definition_id]; - let func_type = if ast_definition.is_function() { - [ConcreteTypePart::Function(definition_id, 0)] - } else if ast_definition.is_component() { - [ConcreteTypePart::Component(definition_id, 0)] + let ast_definition = heap[definition_id].as_procedure(); + let func_type = if ast_definition.kind == ProcedureKind::Function { + [ConcreteTypePart::Function(ast_definition.this, 0)] } else { - assert!(false); - unreachable!() + [ConcreteTypePart::Component(ast_definition.this, 0)] }; let mono_index = types.get_procedure_monomorph_type_id(&definition_id, &func_type).unwrap(); @@ -928,10 +925,14 @@ fn has_equal_num_monomorphs(ctx: TestCtx, num: usize, definition_id: DefinitionI for mono in &ctx.types.mono_types { match &mono.concrete_type.parts[0] { - ConcreteTypePart::Instance(def_id, _) | + ConcreteTypePart::Instance(def_id, _) => { + if *def_id == definition_id { + num_on_type += 1; + } + } ConcreteTypePart::Function(def_id, _) | ConcreteTypePart::Component(def_id, _) => { - if *def_id == definition_id { + if def_id.upcast() == definition_id { num_on_type += 1; } }, @@ -964,11 +965,11 @@ fn has_monomorph(ctx: TestCtx, definition_id: DefinitionId, serialized_monomorph }; // Bit wasteful, but this is (temporary?) testing code: - for (mono_idx, mono) in ctx.types.mono_types.iter().enumerate() { + for (_mono_idx, mono) in ctx.types.mono_types.iter().enumerate() { let got_definition_id = match &mono.concrete_type.parts[0] { - ConcreteTypePart::Instance(v, _) | + ConcreteTypePart::Instance(v, _) => *v, ConcreteTypePart::Function(v, _) | - ConcreteTypePart::Component(v, _) => *v, + ConcreteTypePart::Component(v, _) => v.upcast(), _ => DefinitionId::new_invalid(), }; if got_definition_id == definition_id { diff --git a/src/runtime2/component/component_pdl.rs b/src/runtime2/component/component_pdl.rs index a698dbff39a72205436cb435ab9cd0bf7709cb84..f53b091dacfa1cb043a387b893c130c36fd55614 100644 --- a/src/runtime2/component/component_pdl.rs +++ b/src/runtime2/component/component_pdl.rs @@ -1,5 +1,5 @@ use crate::protocol::*; -use crate::protocol::ast::DefinitionId; +use crate::protocol::ast::ProcedureDefinitionId; use crate::protocol::eval::{ PortId as EvalPortId, Prompt, ValueGroup, Value, @@ -598,7 +598,7 @@ impl CompPDL { fn create_component_and_transfer_ports( &mut self, sched_ctx: &SchedulerCtx, creator_ctx: &mut CompCtx, - definition_id: DefinitionId, type_id: TypeId, mut arguments: ValueGroup + definition_id: ProcedureDefinitionId, type_id: TypeId, mut arguments: ValueGroup ) { struct PortPair{ creator_handle: LocalPortHandle,