diff --git a/src/protocol/ast.rs b/src/protocol/ast.rs index b7f67792ee752cab0bc43c055739301840ec86ad..6f42d75ea68749ad3cc38b3f8e6ff2e935512fd5 100644 --- a/src/protocol/ast.rs +++ b/src/protocol/ast.rs @@ -620,6 +620,18 @@ pub struct Identifier { pub value: Vec } +impl PartialEq for Identifier { + fn eq(&self, other: &Self) -> bool { + return self.value == other.value + } +} + +impl PartialEq for Identifier { + fn eq(&self, other: &NamespacedIdentifier) -> bool { + return self.value == other.value + } +} + #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct NamespacedIdentifier { pub position: InputPosition, @@ -643,7 +655,12 @@ impl PartialEq for NamespacedIdentifier { return self.value == other.value } } -impl Eq for NamespacedIdentifier{} + +impl PartialEq for NamespacedIdentifier { + fn eq(&self, other: &Identifier) -> bool { + return self.value == other.value; + } +} // TODO: Just keep ref to NamespacedIdentifier pub(crate) struct NamespacedIdentifierIter<'a> { @@ -950,6 +967,24 @@ pub enum Literal { Struct(LiteralStruct), } +impl Literal { + pub(crate) fn as_struct(&self) -> &LiteralStruct { + if let Literal::Struct(literal) = self{ + literal + } else { + unreachable!("Attempted to obtain {:?} as Literal::Struct", self) + } + } + + pub(crate) fn as_struct_mut(&mut self) -> &mut LiteralStruct { + if let Literal::Struct(literal) = self{ + literal + } else { + unreachable!("Attempted to obtain {:?} as Literal::Struct", self) + } + } +} + #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct LiteralStructField { // Phase 1: parser @@ -1227,7 +1262,7 @@ impl VariableScope for Definition { fn get_variable(&self, h: &Heap, id: &Identifier) -> Option { for ¶meter_id in self.parameters().iter() { let parameter = &h[parameter_id]; - if parameter.identifier.value == id.value { + if parameter.identifier == *id { return Some(parameter_id.0); } } @@ -1607,7 +1642,7 @@ impl VariableScope for BlockStatement { fn get_variable(&self, h: &Heap, id: &Identifier) -> Option { for local_id in self.locals.iter() { let local = &h[*local_id]; - if local.identifier.value == id.value { + if local.identifier == *id { return Some(local_id.0); } } diff --git a/src/protocol/ast_printer.rs b/src/protocol/ast_printer.rs index 209767533d73ef52f9fcf27d1e63f9291f3f4e9f..18c61d75b6ee0ff14674ad0470b224c4640aeb71 100644 --- a/src/protocol/ast_printer.rs +++ b/src/protocol/ast_printer.rs @@ -621,8 +621,29 @@ impl ASTWriter { Literal::Null => { val.with_s_val("null"); }, Literal::True => { val.with_s_val("true"); }, Literal::False => { val.with_s_val("false"); }, - Literal::Character(char) => { val.with_ascii_val(char); }, - Literal::Integer(int) => { val.with_disp_val(int); }, + Literal::Character(data) => { val.with_ascii_val(data); }, + Literal::Integer(data) => { val.with_disp_val(data); }, + Literal::Struct(data) => { + val.with_s_val("Struct"); + let indent4 = indent3 + 1; + + // Polymorphic arguments + if !data.poly_args.is_empty() { + self.kv(indent3).with_s_key("PolymorphicArguments"); + for poly_arg in &data.poly_args { + self.kv(indent4).with_s_key("Argument") + .with_custom_val(|v| write_parser_type(v, heap, &heap[*poly_arg])); + } + } + + for field in &data.fields { + self.kv(indent3).with_s_key("Field"); + self.kv(indent4).with_s_key("Name").with_ascii_val(&field.identifier.value); + self.kv(indent4).with_s_key("Index").with_disp_val(&field.field_idx); + self.kv(indent4).with_s_key("ParserType"); + self.write_expr(heap, field.value, indent4 + 1); + } + } } self.kv(indent2).with_s_key("Parent") @@ -649,6 +670,15 @@ impl ASTWriter { } } + // Polymorphic arguments + if !expr.poly_args.is_empty() { + self.kv(indent2).with_s_key("PolymorphicArguments"); + for poly_arg in &expr.poly_args { + self.kv(indent3).with_s_key("Argument") + .with_custom_val(|v| write_parser_type(v, heap, &heap[*poly_arg])); + } + } + // Arguments self.kv(indent2).with_s_key("Arguments"); for arg_id in &expr.arguments { diff --git a/src/protocol/eval.rs b/src/protocol/eval.rs index 1f7a71288986d49cbab4f04e145dd9e1c36948ac..0d37e152b5c05da853162089be83102d9ce49477 100644 --- a/src/protocol/eval.rs +++ b/src/protocol/eval.rs @@ -87,6 +87,7 @@ impl Value { } } Literal::Character(_data) => unimplemented!(), + Literal::Struct(_data) => unimplemented!(), } } fn set(&mut self, index: &Value, value: &Value) -> Option { diff --git a/src/protocol/lexer.rs b/src/protocol/lexer.rs index c8061326ab29c160bf1ab6b475677a3fe7039a96..afd0bc50f80ce32e28cbe8fe6b63a6371eeab2c9 100644 --- a/src/protocol/lexer.rs +++ b/src/protocol/lexer.rs @@ -279,8 +279,6 @@ impl Lexer<'_> { if self.consume_whitespace(false).is_err() { return false; } } } - - true } fn consume_ident(&mut self) -> Result, ParseError2> { if !self.has_identifier() { @@ -684,7 +682,7 @@ impl Lexer<'_> { let backup_pos = self.source.pos(); match self.consume_comma_separated( h, b'<', b'>', "Expected the end of the polymorphic variable list", - |lexer, heap| lexer.consume_identifier() + |lexer, _heap| lexer.consume_identifier() )? { Some(poly_vars) => Ok(poly_vars), None => { @@ -2341,7 +2339,7 @@ impl Lexer<'_> { if Some(b'{') == next { let symbols = match self.consume_comma_separated( h, b'{', b'}', "Expected end of import list", - |lexer, heap| { + |lexer, _heap| { // Symbol name let position = lexer.source.pos(); let name = lexer.consume_ident()?; diff --git a/src/protocol/parser/depth_visitor.rs b/src/protocol/parser/depth_visitor.rs index 688745472b8650137f2239dc2f3d98d7bc243e13..06672185b15a041039576e7ca635448c7753fae2 100644 --- a/src/protocol/parser/depth_visitor.rs +++ b/src/protocol/parser/depth_visitor.rs @@ -55,7 +55,7 @@ pub(crate) trait Visitor: Sized { fn visit_local_statement(&mut self, h: &mut Heap, stmt: LocalStatementId) -> VisitorResult { recursive_local_statement(self, h, stmt) } - fn visit_memory_statement(&mut self, h: &mut Heap, stmt: MemoryStatementId) -> VisitorResult { + fn visit_memory_statement(&mut self, _h: &mut Heap, _stmt: MemoryStatementId) -> VisitorResult { Ok(()) } fn visit_channel_statement( @@ -1033,7 +1033,7 @@ impl ResolveLabels { if other_stmt == stmt { continue; } else { - if h[other_stmt].label.value == h[stmt].label.value { + if h[other_stmt].label == h[stmt].label { return Err((h[stmt].position, "Duplicate label".to_string())); } } @@ -1064,7 +1064,7 @@ impl ResolveLabels { // It does not matter in what order we find the labels. // If there are duplicates: that is checked elsewhere. for &stmt in h[block].labels.iter() { - if h[stmt].label.value == id.value { + if h[stmt].label == *id { return Some(stmt); } } diff --git a/src/protocol/parser/type_resolver.rs b/src/protocol/parser/type_resolver.rs index e2ebecf68f9aad56031f77eeee377ee8110bc056..b942f54d8fd068384028f1db81edd3283c33661b 100644 --- a/src/protocol/parser/type_resolver.rs +++ b/src/protocol/parser/type_resolver.rs @@ -1715,10 +1715,8 @@ impl TypeResolvingVisitor { // All elements should have an equal type let progress = self.apply_equal_n_constraint(ctx, upcast_id, &expr_elements)?; - let mut any_progress = false; for (progress_arg, arg_id) in progress.iter().zip(expr_elements.iter()) { if *progress_arg { - any_progress = true; self.queue_expr(*arg_id); } } @@ -1750,11 +1748,20 @@ impl TypeResolvingVisitor { fn progress_constant_expr(&mut self, ctx: &mut Ctx, id: LiteralExpressionId) -> Result<(), ParseError2> { let upcast_id = id.upcast(); let expr = &ctx.heap[id]; - let template = match &expr.value { - Literal::Null => &MESSAGE_TEMPLATE[..], - Literal::Integer(_) => &INTEGERLIKE_TEMPLATE[..], - Literal::True | Literal::False => &BOOL_TEMPLATE[..], - Literal::Character(_) => todo!("character literals") + let progress_expr = match &expr.value { + Literal::Null => { + self.apply_forced_constraint(ctx, upcast_id, &MESSAGE_TEMPLATE)? + }, + Literal::Integer(_) => { + self.apply_forced_constraint(ctx, upcast_id, &INTEGERLIKE_TEMPLATE)? + }, + Literal::True | Literal::False => { + self.apply_forced_constraint(ctx, upcast_id, &BOOL_TEMPLATE)? + }, + Literal::Character(_) => todo!("character literals"), + Literal::Struct(data) => { + + } }; let progress = self.apply_forced_constraint(ctx, upcast_id, template)?; @@ -1982,7 +1989,7 @@ impl TypeResolvingVisitor { // Only perform one-way inference to prevent updating our type, this // would lead to an inconsistency let var_type: *mut _ = &mut var_data.var_type; - let mut link_data = self.var_types.get_mut(&linked_id).unwrap(); + let link_data = self.var_types.get_mut(&linked_id).unwrap(); debug_assert!( unsafe{&*var_type}.parts[0] == InferenceTypePart::Input || @@ -2369,6 +2376,7 @@ impl TypeResolvingVisitor { match definition { Definition::Component(definition) => { + debug_assert_eq!(poly_vars.len(), definition.poly_vars.len()); let mut parameter_types = Vec::with_capacity(definition.parameters.len()); for param_id in definition.parameters.clone() { let param = &ctx.heap[param_id]; @@ -2379,6 +2387,7 @@ impl TypeResolvingVisitor { (parameter_types, InferenceType::new(false, true, vec![InferenceTypePart::Void])) }, Definition::Function(definition) => { + debug_assert!(poly_vars.len(), definition.poly_vars.len()); let mut parameter_types = Vec::with_capacity(definition.parameters.len()); for param_id in definition.parameters.clone() { let param = &ctx.heap[param_id]; @@ -2403,6 +2412,30 @@ impl TypeResolvingVisitor { }); } + fn insert_initial_struct_polymorph_data( + &mut self, ctx: &mut Ctx, lit_id: LiteralExpressionId, + ) { + let literal = ctx.heap[lit_id].value.as_struct(); + + // Handle polymorphic arguments + let mut poly_vars = Vec::with_capacity(literal.poly_args.len()); + for poly_arg_type_id in literal.poly_args.clone() { // TODO: @performance + poly_vars.push(self.determine_inference_type_from_parser_type(ctx, *poly_arg_type_id, true)) + } + + // Handle parser types on struct definition + let definition = &ctx.heap[literal.definition.unwrap()]; + match definition { + Definition::Struct(definition) => { + debug_assert_eq!(poly_vars.len(), definition.poly_vars.len()); + + }, + _ => unreachable!("definition for struct literal does not point to struct definition") + } + + // TODO: Continue here!!! + } + /// Determines the initial InferenceType from the provided ParserType. This /// may be called with two kinds of intentions: /// 1. To resolve a ParserType within the body of a function, or on diff --git a/src/protocol/parser/type_table.rs b/src/protocol/parser/type_table.rs index 3bca3cbece7a6b06ad6dd06a06990e983f925c62..3ffbec0d57854dd810667d2d30eb6f3c5ab44230 100644 --- a/src/protocol/parser/type_table.rs +++ b/src/protocol/parser/type_table.rs @@ -846,7 +846,7 @@ impl TypeTable { // polymorphic arguments. If so then we can halt the // execution for (poly_arg_idx, poly_arg) in poly_vars.iter().enumerate() { - if poly_arg.value == symbolic.identifier.value { + if *poly_arg == symbolic.identifier { set_resolve_result(ResolveResult::PolyArg(poly_arg_idx)); continue 'resolve_loop; } @@ -990,7 +990,7 @@ impl TypeTable { }, PTV::Symbolic(symbolic) => { for (poly_arg_idx, poly_arg) in poly_args.iter_mut().enumerate() { - if poly_arg.identifier.value == symbolic.identifier.value { + if poly_arg.identifier == symbolic.identifier { poly_arg.is_in_use = true; // TODO: If we allow higher-kinded types in the future, // then we can't continue here, but must resolve the @@ -1061,7 +1061,7 @@ impl TypeTable { let item_ident = getter(item); for other_item in &items[0..item_idx] { let other_item_ident = getter(other_item); - if item_ident.value == other_item_ident.value { + if item_ident == other_item_ident { let module_source = &ctx.modules[root_id.index as usize].source; return Err(ParseError2::new_error( module_source, item_ident.position, &format!("This {} is defined more than once", item_name) @@ -1085,7 +1085,7 @@ impl TypeTable { // identifiers conflict with any imported scopes for (arg_idx, poly_arg) in poly_args.iter().enumerate() { for other_poly_arg in &poly_args[..arg_idx] { - if poly_arg.value == other_poly_arg.value { + if poly_arg == other_poly_arg { let module_source = &ctx.modules[root_id.index as usize].source; return Err(ParseError2::new_error( module_source, poly_arg.position, diff --git a/src/protocol/parser/visitor_linker.rs b/src/protocol/parser/visitor_linker.rs index fd24b4fa81e2b85d41ce1abd361fbade0139592a..958e2ac26d3281edfe3d68943527ea95d46179a7 100644 --- a/src/protocol/parser/visitor_linker.rs +++ b/src/protocol/parser/visitor_linker.rs @@ -733,7 +733,6 @@ impl Visitor2 for ValidityAndLinkerVisitor { for (def_field_idx, def_field) in definition.fields.iter().enumerate() { if field.identifier == def_field.identifier { field.field_idx = def_field_idx; - num_found += 1; break; } } @@ -741,7 +740,7 @@ impl Visitor2 for ValidityAndLinkerVisitor { // Check if not found if field.field_idx == FIELD_NOT_FOUND_SENTINEL { return Err(ParseError2::new_error( - &ctx.module.source, field.identifier.position(), + &ctx.module.source, field.identifier.position, &format!( "This field does not exist on the struct '{}'", &String::from_utf8_lossy(&literal.identifier.value), @@ -752,7 +751,7 @@ impl Visitor2 for ValidityAndLinkerVisitor { // Check if specified more than once if specified[field.field_idx] { return Err(ParseError2::new_error( - &ctx.module.source, field.identifier.position(), + &ctx.module.source, field.identifier.position, "This field is specified more than once" )); } @@ -777,15 +776,18 @@ impl Visitor2 for ValidityAndLinkerVisitor { )); } - // Need to traverse fields expressions in struct + // Need to traverse fields expressions in struct and evaluate + // the poly args let old_num_exprs = self.expression_buffer.len(); self.expression_buffer.extend(literal.fields.iter().map(|v| v.value)); let new_num_exprs = self.expression_buffer.len(); + self.visit_literal_poly_args(ctx, id)?; + for expr_idx in old_num_exprs..new_num_exprs { let expr_id = self.expression_buffer[expr_idx]; self.expr_parent = ExpressionParent::Expression(upcast_id, expr_idx as u32); - self.visit_expr(ctx, expr_id) + self.visit_expr(ctx, expr_id); } self.expression_buffer.truncate(old_num_exprs); @@ -858,13 +860,13 @@ impl Visitor2 for ValidityAndLinkerVisitor { num_definition_args = 2; } Method::Symbolic(symbolic) => { - // Find symbolic method - let (verb, expected_type) = if let ExpressionParent::New(_) = self.expr_parent { + // Find symbolic procedure + let expected_type = if let ExpressionParent::New(_) = self.expr_parent { // Expect to find a component - ("instantiated", TypeClass::Component) + TypeClass::Component } else { // Expect to find a function - ("called", TypeClass::Function) + TypeClass::Function }; let definition = self.find_symbol_of_type( @@ -873,7 +875,7 @@ impl Visitor2 for ValidityAndLinkerVisitor { )?; symbolic.definition = Some(definition.ast_definition); - match definition { + match &definition.definition { DefinedTypeVariant::Function(definition) => { num_definition_args = definition.arguments.len(); }, @@ -1074,7 +1076,7 @@ impl ValidityAndLinkerVisitor { let mut symbolic_variant = None; for (poly_var_idx, poly_var) in poly_vars.iter().enumerate() { - if symbolic.identifier.value == poly_var.value { + if symbolic.identifier == *poly_var { // Type refers to a polymorphic variable. // TODO: @hkt Maybe allow higher-kinded types? if !symbolic.poly_args.is_empty() { @@ -1095,7 +1097,6 @@ impl ValidityAndLinkerVisitor { let found_type = find_type_definition( &ctx.symbols, &ctx.types, ctx.module.root_id, &symbolic.identifier ).as_parse_error(&ctx.module.source)?; - symbolic_variant = Some(SymbolicParserTypeVariant::Definition(found_type.ast_definition)); // TODO: @function_ptrs: Allow function pointers at some // point in the future @@ -1212,7 +1213,7 @@ impl ValidityAndLinkerVisitor { // in which the current variable resides. if local.this != *other_local_id && local_relative_pos >= other_local.relative_pos_in_block && - local.identifier.value == other_local.identifier.value { + local.identifier == other_local.identifier { // Collision within this scope return Err( ParseError2::new_error(&ctx.module.source, local.position, "Local variable name conflicts with another variable") @@ -1228,7 +1229,7 @@ impl ValidityAndLinkerVisitor { // At outer scope, check parameters of function/component for parameter_id in ctx.heap[*definition_id].parameters() { let parameter = &ctx.heap[*parameter_id]; - if local.identifier.value == parameter.identifier.value { + if local.identifier == parameter.identifier { return Err( ParseError2::new_error(&ctx.module.source, local.position, "Local variable name conflicts with parameter") .with_postfixed_info(&ctx.module.source, parameter.position, "Parameter definition is found here") @@ -1273,7 +1274,7 @@ impl ValidityAndLinkerVisitor { for local_id in &block.locals { let local = &ctx.heap[*local_id]; - if local.relative_pos_in_block < relative_pos && local.identifier.value == identifier.value { + if local.relative_pos_in_block < relative_pos && local.identifier == *identifier { return Ok(local_id.upcast()); } } @@ -1287,7 +1288,7 @@ impl ValidityAndLinkerVisitor { let definition = &ctx.heap[*definition_id]; for parameter_id in definition.parameters() { let parameter = &ctx.heap[*parameter_id]; - if parameter.identifier.value == identifier.value { + if parameter.identifier == *identifier { return Ok(parameter_id.upcast()); } } @@ -1320,7 +1321,7 @@ impl ValidityAndLinkerVisitor { let block = &ctx.heap[scope.to_block()]; for other_label_id in &block.labels { let other_label = &ctx.heap[*other_label_id]; - if other_label.label.value == label.label.value { + if other_label.label == label.label { // Collision return Err( ParseError2::new_error(&ctx.module.source, label.position, "Label name conflicts with another label") @@ -1357,7 +1358,7 @@ impl ValidityAndLinkerVisitor { let block = &ctx.heap[scope.to_block()]; for label_id in &block.labels { let label = &ctx.heap[*label_id]; - if label.label.value == identifier.value { + if label.label == *identifier { for local_id in &block.locals { // TODO: Better to do this in control flow analysis, it // is legal to skip over a variable declaration if it @@ -1495,6 +1496,7 @@ impl ValidityAndLinkerVisitor { Ok(target) } + // TODO: @cleanup, merge with function below fn visit_call_poly_args(&mut self, ctx: &mut Ctx, call_id: CallExpressionId) -> VisitorResult { let call_expr = &ctx.heap[call_id]; @@ -1571,7 +1573,8 @@ impl ValidityAndLinkerVisitor { fn visit_literal_poly_args(&mut self, ctx: &mut Ctx, lit_id: LiteralExpressionId) -> VisitorResult { let literal_expr = &ctx.heap[lit_id]; - let (num_specified_poly_ags, num_expected_poly_args) = match &literal_expr.value { + let literal_pos = literal_expr.position; + let (num_specified, num_expected) = match &literal_expr.value { Literal::Null | Literal::False | Literal::True | Literal::Character(_) | Literal::Integer(_) => { // Not really an error, but a programmer error as we're likely @@ -1588,22 +1591,52 @@ impl ValidityAndLinkerVisitor { unreachable!(); } }; + let num_specified = literal.poly_args.len(); + + // Visit all embedded parser types (they might not be of the + // correct length, but we check this below) + let old_num_types = self.parser_type_buffer.len(); + self.parser_type_buffer.extend(&literal.poly_args); + while self.parser_type_buffer.len() > old_num_types { + let parser_type_id = self.parser_type_buffer.pop().unwrap(); + self.visit_parser_type(ctx, parser_type_id)?; + } + self.parser_type_buffer.truncate(old_num_types); - (literal.poly_args.len(), num_expected) + (num_specified, num_expected) } }; - if num_specified_poly_ags == 0 { - if num_expected_poly_args != 0 { - let pos = literal_expr.position; - for _ in 0..num_expected_poly_args { + if num_specified == 0 { + // None are specified + if num_expected != 0 { + // So assumed to all be inferred + for _ in 0..num_expected { self.parser_type_buffer.push(ctx.heap.alloc_parser_type(|this| ParserType{ - this, pos, variant: ParserTypeVariant::Inferred + this, pos: literal_pos, variant: ParserTypeVariant::Inferred })); } - let literal_expr = match &mut + let literal = match &mut ctx.heap[lit_id].value { + Literal::Struct(literal) => literal, + _ => unreachable!(), + }; + literal.poly_args.reserve(num_expected); + for _ in 0..num_expected { + literal.poly_args.push(self.parser_type_buffer.pop().unwrap()); + } } + } else if num_specified != num_expected { + // Incorrect specification of poly args + return Err(ParseError2::new_error( + &ctx.module.source, literal_pos, + &format!( + "Expected {} polymorphic arguments (or none, to infer them), but {} were specified", + num_expected, num_specified + ) + )) } + + Ok(()) } } \ No newline at end of file