From 63d65f7baf1882e1961ab55841b841ae942bdc9e 2021-07-22 15:22:00 From: MH Date: 2021-07-22 15:22:00 Subject: [PATCH] stuck again in the abstractions, pending rewrite of visitor --- diff --git a/src/protocol/ast.rs b/src/protocol/ast.rs index fb805022295da6d40b9bf2d38462c8ad09fa99f7..b94f81be548e9f95787e334020dfb98457e8d578 100644 --- a/src/protocol/ast.rs +++ b/src/protocol/ast.rs @@ -494,7 +494,9 @@ pub enum ConcreteTypePart { Input, Output, // User defined type with any number of nested types - Instance(DefinitionId, u32), + Instance(DefinitionId, u32), // instance of data type + Function(DefinitionId, u32), // instance of function + Component(DefinitionId, u32), // instance of a connector } impl ConcreteTypePart { @@ -509,7 +511,9 @@ impl ConcreteTypePart { 0, Array | Slice | Input | Output => 1, - Instance(_, num_embedded) => *num_embedded + Instance(_, num_embedded) => *num_embedded, + Function(_, num_embedded) => *num_embedded, + Component(_, num_embedded) => *num_embedded, } } } @@ -601,7 +605,9 @@ impl ConcreteType { idx = display_part(parts, heap, idx, target); target.push('>'); }, - CTP::Instance(definition_id, num_poly_args) => { + CTP::Instance(definition_id, num_poly_args) | + 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()); diff --git a/src/protocol/parser/pass_definitions.rs b/src/protocol/parser/pass_definitions.rs index 5c88f9d9ed4ccee019a04b1f0a21ae5ca1a7a999..7a48893e72677a23ba5654dfbc30215d74d61db1 100644 --- a/src/protocol/parser/pass_definitions.rs +++ b/src/protocol/parser/pass_definitions.rs @@ -224,7 +224,8 @@ impl PassDefinitions { let value = if has_embedded { types_section.into_vec() } else { - types_section.forget() + types_section.forget(); + Vec::new() }; Ok(UnionVariantDefinition{ diff --git a/src/protocol/parser/pass_typing.rs b/src/protocol/parser/pass_typing.rs index 6d58f7e3853adc9af739ec5c80d7f938617a5e03..a561b8a79846a4b5a9262bb1e30d3a2fd1372b9c 100644 --- a/src/protocol/parser/pass_typing.rs +++ b/src/protocol/parser/pass_typing.rs @@ -1391,10 +1391,23 @@ impl PassTyping { // Helper for transferring polymorphic variables to concrete types and // checking if they're completely specified - fn poly_inference_to_concrete_type( - ctx: &Ctx, expr_id: ExpressionId, inference: &Vec - ) -> Result, ParseError> { - let mut concrete = Vec::with_capacity(inference.len()); + fn inference_type_to_concrete_type( + ctx: &Ctx, expr_id: ExpressionId, inference: &Vec, + first_concrete_part: ConcreteTypePart, + ) -> Result<(ConcreteType, Vec), ParseError> { + // Prepare storage vector + let mut num_inference_parts = 0; + for inference_type in inference { + num_inference_parts += inference_type.parts.len(); + } + + let mut concrete_full_parts = Vec::with_capacity(1 + num_inference_parts); + concrete_full_parts.push(first_concrete_part); + + let mut concrete_poly_args = Vec::with_capacity(inference.len()); + + // Go through all polymorphic arguments and add them to the concrete + // types. for (poly_idx, poly_type) in inference.iter().enumerate() { if !poly_type.is_done { let expr = &ctx.heap[expr_id]; @@ -1419,10 +1432,12 @@ impl PassTyping { let mut concrete_type = ConcreteType::default(); poly_type.write_concrete_type(&mut concrete_type); - concrete.push(concrete_type); + + concrete_full_parts.extend_from_slice(&concrete_type.parts); + concrete_poly_args.push(concrete_type); } - Ok(concrete) + Ok((ConcreteType{ parts: concrete_full_parts }, concrete_poly_args)) } // Inference is now done. But we may still have uninferred types. So we @@ -1458,13 +1473,21 @@ impl PassTyping { // storage of the struct type whose field it is selecting. match &ctx.heap[extra_data.expr_id] { Expression::Call(expr) => { - if expr.method != Method::UserFunction && expr.method != Method::UserComponent { + // 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, extra_data.poly_vars.len() as u32) + } else if expr.method == Method::UserComponent { + ConcreteTypePart::Component(expr.definition, extra_data.poly_vars.len() as u32) + } else { // Builtin function continue; - } + }; let definition_id = expr.definition; - let poly_types = poly_inference_to_concrete_type(ctx, extra_data.expr_id, &extra_data.poly_vars)?; + let (concrete_type, poly_types) = inference_type_to_concrete_type( + ctx, extra_data.expr_id, &extra_data.poly_vars, first_concrete_part + )?; match ctx.types.get_procedure_monomorph_index(&definition_id, &poly_types) { Some(reserved_idx) => { @@ -1491,9 +1514,11 @@ impl PassTyping { Literal::Struct(lit) => lit.definition, _ => unreachable!(), }; - - let poly_types = poly_inference_to_concrete_type(ctx, extra_data.expr_id, &extra_data.poly_vars)?; - let mono_index = ctx.types.add_data_monomorph(&definition_id, poly_types); + let first_concrete_part = ConcreteTypePart::Instance(definition_id, extra_data.poly_vars.len() as u32); + let (concrete_type, poly_types) = inference_type_to_concrete_type( + ctx, extra_data.expr_id, &extra_data.poly_vars, first_concrete_part + )?; + let mono_index = ctx.types.add_data_monomorph(modules, ctx, &definition_id, concrete_type)?; infer_expr.field_or_monomorph_idx = mono_index; }, Expression::Select(_) => { @@ -3519,6 +3544,8 @@ impl PassTyping { CTP::Input => parser_type.push(ITP::Input), CTP::Output => parser_type.push(ITP::Output), CTP::Instance(id, num) => parser_type.push(ITP::Instance(*id, *num)), + CTP::Function(_, _) => unreachable!("function type during concrete to inference type conversion"), + CTP::Component(_, _) => unreachable!("component type during concrete to inference type conversion"), } } } diff --git a/src/protocol/parser/type_table.rs b/src/protocol/parser/type_table.rs index ffc059ed34fbdf8141023a68f86d4d8524d65a83..bf43b44acc9a1d37b2c0440739273ac1aaf8a9fd 100644 --- a/src/protocol/parser/type_table.rs +++ b/src/protocol/parser/type_table.rs @@ -453,7 +453,7 @@ struct TypeLoopBreadcrumb { next_embedded: usize, // for unions, the index into the variant's embedded types } -#[derive(PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq)] enum BreadcrumbResult { TypeExists, PushedBreadcrumb, @@ -642,22 +642,25 @@ impl TypeTable { /// Adds a datatype polymorph to the type table. Will not add the /// monomorph if it is already present, or if the type's polymorphic /// variables are all unused. - pub(crate) fn add_data_monomorph(&mut self, definition_id: &DefinitionId, types: Vec) -> i32 { - let def = self.lookup.get_mut(definition_id).unwrap(); - if !def.is_polymorph { - // Not a polymorph, or polyvars are not used in type definition - return 0; + pub(crate) fn add_data_monomorph( + &mut self, modules: &[Module], ctx: &PassCtx, definition_id: &DefinitionId, concrete_type: ConcreteType + ) -> Result { + debug_assert_eq!(*definition_id, get_concrete_type_definition(&concrete_type)); + + // Check if the monomorph already exists + let poly_type = self.lookup.get_mut(definition_id).unwrap(); + if let Some(idx) = poly_type.get_monomorph_index(&concrete_type) { + return idx as i32; } - let monos = def.definition.data_monomorphs_mut(); - if let Some(index) = monos.iter().position(|v| v.poly_args == types) { - // We already know about this monomorph - return index as i32; - } + // Doesn't exist, so instantiate a monomorph and determine its memory + // layout. + self.detect_and_resolve_type_loops_for(modules, ctx, concrete_type)?; + debug_assert_eq!(self.encountered_types[0].definition_id, definition_id); + let mono_idx = self.encountered_types[0].monomorph_idx; + self.lay_out_memory_for_encountered_types(ctx); - let index = monos.len(); - monos.push(DataMonomorph{ poly_args: types }); - return index as i32; + return mono_idx as i32; } //-------------------------------------------------------------------------- @@ -1170,7 +1173,8 @@ impl TypeTable { let breadcrumb = &mut self.breadcrumbs[breadcrumb_idx]; let mut is_union = false; - match self.lookup.get_mut(&breadcrumb.definition_id).unwrap() { + let entry = self.lookup.get_mut(&breadcrumb.definition_id).unwrap(); + match &mut entry.definition { DTV::Union(definition) => { // Mark the currently processed variant as requiring heap // allocation, then advance the *embedded* type. The loop above @@ -1374,7 +1378,7 @@ impl TypeTable { mono_idx }, DTV::Function(_) | DTV::Component(_) => { - unreachable!("pushing type resolving breadcrumb for procedure type {:?}", base_type) + unreachable!("pushing type resolving breadcrumb for procedure type") }, }; @@ -1439,11 +1443,11 @@ impl TypeTable { // Not builtin, but if all code is working correctly, we only care // about the polymorphic argument at this point. - if let PTV::PolymorphicArgument(_container_definition_id, poly_arg_idx) = member_part { - debug_assert_eq!(*_container_definition_id, get_concrete_type_definition(container_type)); + if let PTV::PolymorphicArgument(_container_definition_id, poly_arg_idx) = member_part.variant { + debug_assert_eq!(_container_definition_id, get_concrete_type_definition(container_type)); let mut container_iter = container_type.embedded_iter(0); - for _ in 0..*poly_arg_idx { + for _ in 0..poly_arg_idx { container_iter.next(); }