diff --git a/src/protocol/ast.rs b/src/protocol/ast.rs index 63c154ac40a2ef0ede62bd9f1f2b0557a4d7c9cc..fd5f3dafd7546664dd5a6f7bb2531f94e57c351f 100644 --- a/src/protocol/ast.rs +++ b/src/protocol/ast.rs @@ -675,6 +675,7 @@ impl NamespacedIdentifierPart { /// parsing phase (e.g. Foo::Bar::Qux). But in our current language /// implementation we can only have valid namespaced identifier that contain one /// set of polymorphic arguments at the appropriate position. +/// TODO: @tokens Reimplement/rename once we have a tokenizer #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct NamespacedIdentifier2 { pub position: InputPosition, @@ -684,6 +685,26 @@ pub struct NamespacedIdentifier2 { } impl NamespacedIdentifier2 { + /// Returns the identifier value without any of the specific polymorphic + /// arguments. + pub fn strip_poly_args(&self) -> Vec { + debug_assert!(!self.parts.is_empty() && self.parts[0].is_identifier()); + + let mut result = Vec::with_capacity(self.value.len()); + let mut iter = self.iter(); + let (first_ident, _) = iter.next().unwrap(); + result.extend(first_ident); + + for (ident, _) in iter.next() { + result.push(b':'); + result.push(b':'); + result.extend(ident); + } + + result + } + + /// Returns an iterator of the elements in the namespaced identifier pub fn iter(&self) -> NamespacedIdentifier2Iter { return NamespacedIdentifier2Iter{ identifier: self, @@ -691,23 +712,59 @@ impl NamespacedIdentifier2 { } } - pub fn has_poly_args(&self) -> bool { - return !self.poly_args.is_empty(); + pub fn get_poly_args(&self) -> Option<&[ParserTypeId]> { + let has_poly_args = self.parts.iter().any(|v| !v.is_identifier()); + if has_poly_args { + Some(&self.poly_args) + } else { + None + } } -} -impl PartialEq for NamespacedIdentifier2 { - fn eq(&self, other: &Self) -> bool { - return self.value == other.value + // Check if two namespaced identifiers match eachother when not considering + // the polymorphic arguments + pub fn matches_namespaced_identifier(&self, other: &Self) -> bool { + let mut iter_self = self.iter(); + let mut iter_other = other.iter(); + + loop { + let val_self = iter_self.next(); + let val_other = iter_other.next(); + if val_self.is_some() != val_other.is_some() { + // One is longer than the other + return false; + } + if val_self.is_none() { + // Both are none + return true; + } + + // Both are something + let (val_self, _) = val_self.unwrap(); + let (val_other, _) = val_other.unwrap(); + if val_self != val_other { return false; } + } } -} -impl PartialEq for NamespacedIdentifier2 { - fn eq(&self, other: &Identifier) -> bool { - return self.value == other.value + // Check if the namespaced identifier matches an identifier when not + // considering the polymorphic arguments + pub fn matches_identifier(&self, other: &Identifier) -> bool { + let mut iter = self.iter(); + let (first_ident, _) = iter.next().unwrap(); + if first_ident != other.value { + return false; + } + + if iter.next().is_some() { + return false; + } + + return true; } } +/// Iterator over elements of the namespaced identifier. The element index will +/// only ever be at the start of an identifier element. #[derive(Debug)] pub struct NamespacedIdentifier2Iter<'a> { identifier: &'a NamespacedIdentifier2, @@ -718,9 +775,12 @@ impl<'a> Iterator for NamespacedIdentifier2Iter<'a> { type Item = (&'a [u8], Option<&'a [ParserTypeId]>); fn next(&mut self) -> Option { match self.get(self.element_idx) { - Some(result) => { + Some((ident, poly)) => { self.element_idx += 1; - Some(result) + if poly.is_some() { + self.element_idx += 1; + } + Some((ident, poly)) }, None => None } @@ -728,6 +788,9 @@ impl<'a> Iterator for NamespacedIdentifier2Iter<'a> { } impl<'a> NamespacedIdentifier2Iter<'a> { + /// Returns number of parts iterated over, may not correspond to number of + /// times one called `next()` because returning an identifier with + /// polymorphic arguments increments the internal counter by 2. pub fn num_returned(&self) -> usize { return self.element_idx; } @@ -736,13 +799,25 @@ impl<'a> NamespacedIdentifier2Iter<'a> { return self.identifier.parts.len() - self.element_idx; } + pub fn returned_section(&self) -> &[u8] { + if self.element_idx == 0 { return &self.identifier.value[0..0]; } + + let last_idx = match &self.identifier.parts[self.element_idx - 1] { + NamespacedIdentifierPart::Identifier{end, ..} => *end, + NamespacedIdentifierPart::PolyArgs{end, ..} => *end, + }; + + return &self.identifier.value[..last_idx as usize]; + } + + /// Returns a specific element from the namespaced identifier pub fn get(&self, idx: usize) -> Option<::Item> { if idx >= self.identifier.parts.len() { return None } let cur_part = &self.identifier.parts[idx]; - let next_part = self.identifier.parts.get(idx); + let next_part = self.identifier.parts.get(idx + 1); let (ident_start, ident_end) = cur_part.as_identifier(); let poly_slice = match next_part { @@ -761,12 +836,29 @@ impl<'a> NamespacedIdentifier2Iter<'a> { )) } - pub fn prev(&self) -> Option<::Item> { - if self.element_idx == 0 { + /// Returns the previously returend index into the parts array of the + /// identifier. + pub fn prev_idx(&self) -> Option { + if self.element_idx == 0 { return None; + }; + + if self.identifier.parts[self.element_idx - 1].is_identifier() { + return Some(self.element_idx - 1); } - self.get(self.element_idx - 1) + // Previous part had polymorphic arguments, so the one before that must + // be an identifier (if well formed) + debug_assert!(self.element_idx >= 2 && self.identifier.parts[self.element_idx - 2].is_identifier()); + return Some(self.element_idx - 2) + } + + /// Returns the previously returned result from `next()` + pub fn prev(&self) -> Option<::Item> { + match self.prev_idx() { + None => None, + Some(idx) => self.get(idx) + } } } @@ -912,6 +1004,7 @@ pub struct SymbolicParserType { pub identifier: NamespacedIdentifier2, // Phase 2: validation/linking (for types in function/component bodies) and // type table construction (for embedded types of structs/unions) + pub poly_args2: Vec, // taken from identifier or inferred pub variant: Option } @@ -1133,6 +1226,7 @@ pub struct LiteralStruct { pub(crate) identifier: NamespacedIdentifier2, pub(crate) fields: Vec, // Phase 2: linker + pub(crate) poly_args2: Vec, // taken from identifier pub(crate) definition: Option } diff --git a/src/protocol/ast_printer.rs b/src/protocol/ast_printer.rs index 35f95d5823ea4394b6d541dab939338c8a947896..316094c00f9b488d9e42b09103a96b0c42f64e63 100644 --- a/src/protocol/ast_printer.rs +++ b/src/protocol/ast_printer.rs @@ -237,7 +237,7 @@ impl ASTWriter { .with_s_key("ImportModule"); self.kv(indent2).with_s_key("Name").with_ascii_val(&import.module_name); - self.kv(indent2).with_s_key("Alias").with_ascii_val(&import.alias); + self.kv(indent2).with_s_key("Alias").with_ascii_val(&import.alias.value); self.kv(indent2).with_s_key("Target") .with_opt_disp_val(import.module_id.as_ref().map(|v| &v.index)); }, @@ -255,8 +255,8 @@ impl ASTWriter { let indent4 = indent3 + 1; for symbol in &import.symbols { self.kv(indent3).with_s_key("AliasedSymbol"); - self.kv(indent4).with_s_key("Name").with_ascii_val(&symbol.name); - self.kv(indent4).with_s_key("Alias").with_ascii_val(&symbol.alias); + self.kv(indent4).with_s_key("Name").with_ascii_val(&symbol.name.value); + self.kv(indent4).with_s_key("Alias").with_ascii_val(&symbol.alias.value); self.kv(indent4).with_s_key("Definition") .with_opt_disp_val(symbol.definition_id.as_ref().map(|v| &v.index)); } @@ -630,9 +630,9 @@ impl ASTWriter { let indent4 = indent3 + 1; // Polymorphic arguments - if !data.poly_args.is_empty() { + if !data.poly_args2.is_empty() { self.kv(indent3).with_s_key("PolymorphicArguments"); - for poly_arg in &data.poly_args { + for poly_arg in &data.poly_args2 { self.kv(indent4).with_s_key("Argument") .with_custom_val(|v| write_parser_type(v, heap, &heap[*poly_arg])); } @@ -771,7 +771,7 @@ fn write_parser_type(target: &mut String, heap: &Heap, t: &ParserType) { target.push_str("{None}"); } } - embedded.extend(&symbolic.poly_args); + embedded.extend(&symbolic.poly_args2); } }; diff --git a/src/protocol/lexer.rs b/src/protocol/lexer.rs index 9a8f3a73c3d40fa8007aae4686e1831ca7762635..84e882204871f98f1b2b02ac456749e6b97a95e9 100644 --- a/src/protocol/lexer.rs +++ b/src/protocol/lexer.rs @@ -6,10 +6,10 @@ const MAX_NAMESPACES: u8 = 8; // only three levels are supported at the moment macro_rules! debug_log { ($format:literal) => { - enabled_debug_print!(false, "lexer", $format); + enabled_debug_print!(true, "lexer", $format); }; ($format:literal, $($args:expr),*) => { - enabled_debug_print!(false, "lexer", $format, $($args),*); + enabled_debug_print!(true, "lexer", $format, $($args),*); }; } @@ -94,6 +94,19 @@ fn lowercase(x: u8) -> u8 { } } +fn identifier_as_namespaced(identifier: Identifier) -> NamespacedIdentifier2 { + let identifier_len = identifier.value.len(); + debug_assert!(identifier_len < u16::max_value() as usize); + NamespacedIdentifier2{ + position: identifier.position, + value: identifier.value, + poly_args: Vec::new(), + parts: vec![ + NamespacedIdentifierPart::Identifier{start: 0, end: identifier_len as u16} + ], + } +} + pub struct Lexer<'a> { source: &'a mut InputSource, level: usize, @@ -478,6 +491,10 @@ impl Lexer<'_> { // Consumes a part of the namespaced identifier, returns a boolean // indicating whether polymorphic arguments were specified. + // TODO: Continue here: if we fail to properly parse the polymorphic + // arguments, assume we have reached the end of the namespaced + // identifier and are instead dealing with a less-than operator. Ugly? + // Yes. Needs tokenizer? Yes. fn consume_part( l: &mut Lexer, h: &mut Heap, ident: &mut NamespacedIdentifier2, backup_pos: &mut InputPosition @@ -630,7 +647,7 @@ impl Lexer<'_> { } else { // Must be a symbolic type let identifier = self.consume_namespaced_identifier2(h)?; - ParserTypeVariant::Symbolic(SymbolicParserType{identifier, variant: None}) + ParserTypeVariant::Symbolic(SymbolicParserType{identifier, variant: None, poly_args2: Vec::new()}) }; // If the type was a basic type (not supporting polymorphic type @@ -1557,6 +1574,7 @@ impl Lexer<'_> { value: Literal::Struct(LiteralStruct{ identifier, fields, + poly_args2: Vec::new(), definition: None, }), parent: ExpressionParent::None, @@ -1590,8 +1608,10 @@ impl Lexer<'_> { let position = self.source.pos(); // Consume method identifier + // TODO: @token Replace this conditional polymorphic arg parsing once we have a tokenizer. debug_log!("consume_call_expression: {}", debug_line!(self.source)); let method; + let mut consume_poly_args_explicitly = true; if self.has_keyword(b"get") { self.consume_keyword(b"get")?; method = Method::Get; @@ -1609,12 +1629,17 @@ impl Lexer<'_> { method = Method::Symbolic(MethodSymbolic{ identifier, definition: None - }) - } + }); + consume_poly_args_explicitly = false; + }; // Consume polymorphic arguments - self.consume_whitespace(false)?; - let poly_args = self.consume_polymorphic_args(h, true)?.unwrap_or_default(); + let poly_args = if consume_poly_args_explicitly { + self.consume_whitespace(false)?; + self.consume_polymorphic_args(h, true)?.unwrap_or_default() + } else { + Vec::new() + }; // Consume arguments to call self.consume_whitespace(false)?; @@ -1650,7 +1675,10 @@ impl Lexer<'_> { ) -> Result { let position = self.source.pos(); debug_log!("consume_variable_expression: {}", debug_line!(self.source)); - let identifier = self.consume_namespaced_identifier()?; + + // TODO: @token Reimplement when tokenizer is implemented, prevent ambiguities + let identifier = identifier_as_namespaced(self.consume_identifier()?); + Ok(h.alloc_variable_expression(|this| VariableExpression { this, position, @@ -1911,11 +1939,7 @@ impl Lexer<'_> { let variable_expr_id = h.alloc_variable_expression(|this| VariableExpression{ this, position: identifier.position.clone(), - identifier: NamespacedIdentifier { - position: identifier.position.clone(), - num_namespaces: 1, - value: identifier.value.clone(), - }, + identifier: identifier_as_namespaced(identifier), declaration: None, parent: ExpressionParent::None, concrete_type: Default::default() diff --git a/src/protocol/parser/mod.rs b/src/protocol/parser/mod.rs index 76e660b1d3512c2979416ff1a4ae81e52c3463af..84c8854902b43975ae27047056999e5c16911e85 100644 --- a/src/protocol/parser/mod.rs +++ b/src/protocol/parser/mod.rs @@ -167,7 +167,7 @@ impl Parser { for symbol in &mut import.symbols { debug_assert!(symbol.definition_id.is_none(), "symbol import already resolved"); - let (_, target_definition_id) = self.symbol_table.resolve_symbol(module_root_id, &symbol.alias) + let (_, target_definition_id) = self.symbol_table.resolve_identifier(module_root_id, &symbol.alias) .expect("symbol import is resolved by symbol table") .as_definition() .expect("symbol import does not resolve to namespace symbol"); diff --git a/src/protocol/parser/symbol_table.rs b/src/protocol/parser/symbol_table.rs index b310f039839b573bd8e08430c6f8a84dd9dc1ce4..89c19f709e402670704f3f77d4971d18d8585723 100644 --- a/src/protocol/parser/symbol_table.rs +++ b/src/protocol/parser/symbol_table.rs @@ -23,20 +23,7 @@ impl SymbolKey { } fn from_namespaced_identifier(module_id: RootId, symbol: &NamespacedIdentifier2) -> Self { - // Strip polymorpic arguments from the identifier - let symbol_name = Vec::with_capacity(symbol.value.len()); - debug_assert!(symbol.parts.len() > 0 && symbol.parts[0].is_identifier()); - - let mut iter = symbol.iter(); - let (first_ident, _) = iter.next().unwrap(); - symbol_name.extend(first_ident); - - for (ident, _) in iter { - symbol_name.push(b':'); - symbol_name.extend(ident); - } - - Self{ module_id, symbol_name } + Self{ module_id, symbol_name: symbol.strip_poly_args() } } } @@ -326,6 +313,20 @@ impl SymbolTable { self.module_lookup.get(identifier).map(|v| *v) } + pub(crate) fn resolve_symbol<'t>( + &'t self, root_module_id: RootId, identifier: &[u8] + ) -> Option<&'t SymbolValue> { + let lookup_key = SymbolKey{ module_id: root_module_id, symbol_name: Vec::from(identifier) }; + self.symbol_lookup.get(&lookup_key) + } + + pub(crate) fn resolve_identifier<'t>( + &'t self, root_module_id: RootId, identifier: &Identifier + ) -> Option<&'t SymbolValue> { + let lookup_key = SymbolKey::from_identifier(root_module_id, identifier); + self.symbol_lookup.get(&lookup_key) + } + /// Resolves a namespaced symbol. This method will go as far as possible in /// going to the right symbol. It will halt the search when: /// 1. Polymorphic arguments are encountered on the identifier. @@ -333,7 +334,7 @@ impl SymbolTable { /// 3. A part of the identifier couldn't be resolved to anything /// The returned iterator will always point to the next symbol (even if /// nothing was found) - pub(crate) fn resolve_namespaced_symbol<'t, 'i>( + pub(crate) fn resolve_namespaced_identifier<'t, 'i>( &'t self, root_module_id: RootId, identifier: &'i NamespacedIdentifier2 ) -> (Option<&'t SymbolValue>, NamespacedIdentifier2Iter<'i>) { let mut iter = identifier.iter(); diff --git a/src/protocol/parser/type_resolver.rs b/src/protocol/parser/type_resolver.rs index 955da8b3756a28ff7ade6220b696e3c65de5b784..4d6fa9f4447a2ed62720f2db5d3d4319eed02adb 100644 --- a/src/protocol/parser/type_resolver.rs +++ b/src/protocol/parser/type_resolver.rs @@ -2767,9 +2767,9 @@ impl TypeResolvingVisitor { let literal = ctx.heap[lit_id].value.as_struct(); // Handle polymorphic arguments - let mut poly_vars = Vec::with_capacity(literal.poly_args.len()); + let mut poly_vars = Vec::with_capacity(literal.poly_args2.len()); let mut total_num_poly_parts = 0; - for poly_arg_type_id in literal.poly_args.clone() { // TODO: @performance + for poly_arg_type_id in literal.poly_args2.clone() { // TODO: @performance let inference_type = self.determine_inference_type_from_parser_type( ctx, poly_arg_type_id, true ); @@ -2931,7 +2931,7 @@ impl TypeResolvingVisitor { match symbolic.variant.as_ref().unwrap() { SymbolicParserTypeVariant::PolyArg(_, arg_idx) => { let arg_idx = *arg_idx; - debug_assert!(symbolic.poly_args.is_empty()); // TODO: @hkt + debug_assert!(symbolic.poly_args2.is_empty()); // TODO: @hkt if parser_type_in_body { // Polymorphic argument refers to definition's @@ -2960,14 +2960,14 @@ impl TypeResolvingVisitor { Definition::Enum(v) => v.poly_vars.len(), _ => unreachable!(), }; - debug_assert_eq!(symbolic.poly_args.len(), num_poly); + debug_assert_eq!(symbolic.poly_args2.len(), num_poly); } - infer_type.push(ITP::Instance(*definition_id, symbolic.poly_args.len())); - let mut poly_arg_idx = symbolic.poly_args.len(); + infer_type.push(ITP::Instance(*definition_id, symbolic.poly_args2.len())); + let mut poly_arg_idx = symbolic.poly_args2.len(); while poly_arg_idx > 0 { poly_arg_idx -= 1; - to_consider.push_front(symbolic.poly_args[poly_arg_idx]); + to_consider.push_front(symbolic.poly_args2[poly_arg_idx]); } } } diff --git a/src/protocol/parser/type_table.rs b/src/protocol/parser/type_table.rs index 49841495a3f33c2e8fffaff9246eb741fe827e60..70864808b1ae924ec18d324dcea70e5253bcfea3 100644 --- a/src/protocol/parser/type_table.rs +++ b/src/protocol/parser/type_table.rs @@ -109,7 +109,7 @@ pub struct DefinedType { pub(crate) ast_root: RootId, pub(crate) ast_definition: DefinitionId, pub(crate) definition: DefinedTypeVariant, - pub(crate) poly_args: Vec, + pub(crate) poly_vars: Vec, pub(crate) is_polymorph: bool, pub(crate) is_pointerlike: bool, // TODO: @optimize @@ -127,7 +127,7 @@ impl DefinedType { } pub(crate) fn has_monomorph(&self, types: &Vec) -> bool { - debug_assert_eq!(self.poly_args.len(), types.len(), "mismatch in number of polymorphic types"); + debug_assert_eq!(self.poly_vars.len(), types.len(), "mismatch in number of polymorphic types"); for monomorph in &self.monomorphs { if monomorph == types { return true; } } @@ -144,9 +144,9 @@ pub enum DefinedTypeVariant { Component(ComponentType) } -pub struct PolyArg { +pub struct PolyVar { identifier: Identifier, - /// Whether the polymorphic argument is used directly in the definition of + /// Whether the polymorphic variables is used directly in the definition of /// the type (not including bodies of function/component types) is_in_use: bool, } @@ -497,7 +497,7 @@ impl TypeTable { )?; self.check_poly_args_collision(ctx, root_id, &definition.poly_vars)?; - let mut poly_args = self.create_initial_poly_args(&definition.poly_vars); + let mut poly_args = self.create_initial_poly_vars(&definition.poly_vars); for variant in &variants { if let Some(embedded) = variant.parser_type { self.check_and_resolve_embedded_type_and_modify_poly_args(ctx, definition_id, &mut poly_args, root_id, embedded)?; @@ -513,7 +513,7 @@ impl TypeTable { variants, tag_representation: Self::enum_tag_type(-1, tag_value), }), - poly_args, + poly_vars: poly_args, is_polymorph, is_pointerlike: false, // TODO: @cyclic_types monomorphs: Vec::new() @@ -565,7 +565,7 @@ impl TypeTable { variants, representation: Self::enum_tag_type(min_enum_value, max_enum_value) }), - poly_args: self.create_initial_poly_args(&definition.poly_vars), + poly_vars: self.create_initial_poly_vars(&definition.poly_vars), is_polymorph: false, is_pointerlike: false, monomorphs: Vec::new() @@ -608,7 +608,7 @@ impl TypeTable { self.check_poly_args_collision(ctx, root_id, &definition.poly_vars)?; // Construct representation of polymorphic arguments - let mut poly_args = self.create_initial_poly_args(&definition.poly_vars); + let mut poly_args = self.create_initial_poly_vars(&definition.poly_vars); for field in &fields { self.check_and_resolve_embedded_type_and_modify_poly_args(ctx, definition_id, &mut poly_args, root_id, field.parser_type)?; } @@ -621,7 +621,7 @@ impl TypeTable { definition: DefinedTypeVariant::Struct(StructType{ fields, }), - poly_args, + poly_vars: poly_args, is_polymorph, is_pointerlike: false, // TODO: @cyclic monomorphs: Vec::new(), @@ -676,7 +676,7 @@ impl TypeTable { self.check_poly_args_collision(ctx, root_id, &definition.poly_vars)?; // Construct polymorphic arguments - let mut poly_args = self.create_initial_poly_args(&definition.poly_vars); + let mut poly_args = self.create_initial_poly_vars(&definition.poly_vars); let return_type_id = definition.return_type; self.check_and_resolve_embedded_type_and_modify_poly_args(ctx, definition_id, &mut poly_args, root_id, return_type_id)?; for argument in &arguments { @@ -693,7 +693,7 @@ impl TypeTable { return_type, arguments, }), - poly_args, + poly_vars: poly_args, is_polymorph, is_pointerlike: false, // TODO: @cyclic monomorphs: Vec::new(), @@ -740,7 +740,7 @@ impl TypeTable { self.check_poly_args_collision(ctx, root_id, &definition.poly_vars)?; // Construct polymorphic arguments - let mut poly_args = self.create_initial_poly_args(&definition.poly_vars); + let mut poly_args = self.create_initial_poly_vars(&definition.poly_vars); for argument in &arguments { self.check_and_resolve_embedded_type_and_modify_poly_args(ctx, definition_id, &mut poly_args, root_id, argument.parser_type)?; } @@ -755,7 +755,7 @@ impl TypeTable { variant: component_variant, arguments, }), - poly_args, + poly_vars: poly_args, is_polymorph, is_pointerlike: false, // TODO: @cyclic monomorphs: Vec::new(), @@ -857,14 +857,14 @@ impl TypeTable { // polymorphic arguments. If so then we can halt the // execution for (poly_arg_idx, poly_arg) in poly_vars.iter().enumerate() { - if symbolic.identifier == *poly_arg { + if symbolic.identifier.matches_identifier(poly_arg) { set_resolve_result(ResolveResult::PolyArg(poly_arg_idx)); continue 'resolve_loop; } } // Lookup the definition in the symbol table - let (symbol, mut ident_iter) = ctx.symbols.resolve_namespaced_symbol(root_id, &symbolic.identifier); + let (symbol, mut ident_iter) = ctx.symbols.resolve_namespaced_identifier(root_id, &symbolic.identifier); if symbol.is_none() { return Err(ParseError2::new_error( &ctx.modules[root_id.index as usize].source, symbolic.identifier.position, @@ -965,10 +965,10 @@ impl TypeTable { return Ok(resolve_result.unwrap()) } - fn create_initial_poly_args(&self, poly_args: &[Identifier]) -> Vec { + fn create_initial_poly_vars(&self, poly_args: &[Identifier]) -> Vec { poly_args .iter() - .map(|v| PolyArg{ identifier: v.clone(), is_in_use: false }) + .map(|v| PolyVar{ identifier: v.clone(), is_in_use: false }) .collect() } @@ -987,7 +987,7 @@ impl TypeTable { /// user-defined type. fn check_and_resolve_embedded_type_and_modify_poly_args( &mut self, ctx: &mut TypeCtx, - type_definition_id: DefinitionId, poly_args: &mut [PolyArg], + type_definition_id: DefinitionId, poly_args: &mut [PolyVar], root_id: RootId, embedded_type_id: ParserTypeId, ) -> Result<(), ParseError2> { use ParserTypeVariant as PTV; @@ -1013,17 +1013,17 @@ impl TypeTable { PTV::Array(subtype_id) | PTV::Input(subtype_id) | PTV::Output(subtype_id) => { - // Outer type is fixed, but inner type might be symbolix + // Outer type is fixed, but inner type might be symbolic self.parser_type_iter.push_back(*subtype_id); }, PTV::Symbolic(symbolic) => { for (poly_arg_idx, poly_arg) in poly_args.iter_mut().enumerate() { - if symbolic.identifier == poly_arg.identifier { + if symbolic.identifier.matches_identifier(&poly_arg.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 // polyargs as well - debug_assert!(!symbolic.identifier.has_poly_args(), "got polymorphic arguments to a polymorphic variable"); + debug_assert!(symbolic.identifier.get_poly_args().is_none(), "got polymorphic arguments to a polymorphic variable"); debug_assert!(symbolic.variant.is_none(), "symbolic parser type's variant already resolved"); symbolic.variant = Some(SymbolicParserTypeVariant::PolyArg(type_definition_id, poly_arg_idx)); continue 'type_loop; @@ -1031,56 +1031,51 @@ impl TypeTable { } // Must match a definition - let (symbol, _) = ctx.symbols.resolve_namespaced_symbol(root_id, &symbolic.identifier); + let (symbol, ident_iter) = ctx.symbols.resolve_namespaced_identifier(root_id, &symbolic.identifier); debug_assert!(symbol.is_some(), "could not resolve symbolic parser type when determining poly args"); - let (symbol, ident_iter) = symbol.unwrap(); + let symbol = symbol.unwrap(); debug_assert_eq!(ident_iter.num_remaining(), 0, "no exact symbol match when determining poly args"); let (_root_id, definition_id) = symbol.as_definition().unwrap(); // Must be a struct, enum, or union, we checked this let defined_type = self.lookup.get(&definition_id).unwrap(); + let (_, poly_args) = ident_iter.prev().unwrap(); + let poly_args = poly_args.unwrap_or_default(); + if cfg!(debug_assertions) { - // Make sure type class is correct + // Everything here should already be checked in + // `resolve_base_parser_type`. let type_class = defined_type.definition.type_class(); debug_assert!( type_class == TypeClass::Struct || type_class == TypeClass::Enum || type_class == TypeClass::Union, "embedded type's class is not struct, enum or union" ); - // Make sure polymorphic arguments occurred at the end - let num_poly = symbolic.identifier.iter() - .map(|(_, v)| v) - .filter(|v| v.is_some()) - .count(); - debug_assert!(num_poly <= 1, "more than one section with polymorphic arguments"); - if num_poly == 1 { - let (_, poly_args) = symbolic.identifier.iter().last().unwrap(); - debug_assert!(poly_args.is_some(), "got poly args, but not at end of identifier"); - } + debug_assert_eq!(poly_args.len(), symbolic.identifier.poly_args.len()); } - if symbolic.poly_args.len() != defined_type.poly_args.len() { + if poly_args.len() != defined_type.poly_vars.len() { // Mismatch in number of polymorphic arguments. This is // not allowed in type definitions (no inference is // allowed within type definitions, only in bodies of // functions/components). let module_source = &ctx.modules[root_id.index as usize].source; - let number_args_msg = if defined_type.poly_args.is_empty() { + let number_args_msg = if defined_type.poly_vars.is_empty() { String::from("is not polymorphic") } else { - format!("accepts {} polymorphic arguments", defined_type.poly_args.len()) + format!("accepts {} polymorphic arguments", defined_type.poly_vars.len()) }; return Err(ParseError2::new_error( module_source, symbolic.identifier.position, &format!( "The type '{}' {}, but {} polymorphic arguments were provided", - String::from_utf8_lossy(&symbolic.identifier.value), - number_args_msg, symbolic.poly_args.len() + String::from_utf8_lossy(&symbolic.identifier.strip_poly_args()), + number_args_msg, poly_args.len() ) )); } - self.parser_type_iter.extend(&symbolic.poly_args); + self.parser_type_iter.extend(poly_args); debug_assert!(symbolic.variant.is_none(), "symbolic parser type's variant already resolved"); symbolic.variant = Some(SymbolicParserTypeVariant::Definition(definition_id)); } diff --git a/src/protocol/parser/utils.rs b/src/protocol/parser/utils.rs index a68e03356b52591d295f8764faf987dfd6b221b9..f7bcc9d066cdc370fe97a75668528869400261c7 100644 --- a/src/protocol/parser/utils.rs +++ b/src/protocol/parser/utils.rs @@ -6,11 +6,11 @@ use super::type_table::*; /// Utility result type. pub(crate) enum FindTypeResult<'t, 'i> { // Found the type exactly - Found(&'t DefinedType), + Found((&'t DefinedType, NamespacedIdentifier2Iter<'i>)), // Could not match symbol SymbolNotFound{ident_pos: InputPosition}, // Matched part of the namespaced identifier, but not completely - SymbolPartial{ident_pos: InputPosition, symbol_pos: InputPosition, ident_iter: NamespacedIdentifierIter<'i>}, + SymbolPartial{ident_pos: InputPosition, symbol_pos: InputPosition, ident_iter: NamespacedIdentifier2Iter<'i>}, // Symbol matched, but points to a namespace/module instead of a type SymbolNamespace{ident_pos: InputPosition, symbol_pos: InputPosition}, } @@ -20,7 +20,7 @@ impl<'t, 'i> FindTypeResult<'t, 'i> { /// Utility function to transform the `FindTypeResult` into a `Result` where /// `Ok` contains the resolved type, and `Err` contains a `ParseError` which /// can be readily returned. This is the most common use. - pub(crate) fn as_parse_error(self, module_source: &InputSource) -> Result<&'t DefinedType, ParseError2> { + pub(crate) fn as_parse_error(self, module_source: &InputSource) -> Result<(&'t DefinedType, NamespacedIdentifier2Iter<'i>), ParseError2> { match self { FindTypeResult::Found(defined_type) => Ok(defined_type), FindTypeResult::SymbolNotFound{ident_pos} => { @@ -59,16 +59,16 @@ impl<'t, 'i> FindTypeResult<'t, 'i> { /// must be a type, not a namespace. pub(crate) fn find_type_definition<'t, 'i>( symbols: &SymbolTable, types: &'t TypeTable, - root_id: RootId, identifier: &'i NamespacedIdentifier + root_id: RootId, identifier: &'i NamespacedIdentifier2 ) -> FindTypeResult<'t, 'i> { // Lookup symbol - let symbol = symbols.resolve_namespaced_symbol(root_id, identifier); + let (symbol, ident_iter) = symbols.resolve_namespaced_identifier(root_id, identifier); if symbol.is_none() { return FindTypeResult::SymbolNotFound{ident_pos: identifier.position}; } // Make sure we resolved it exactly - let (symbol, ident_iter) = symbol.unwrap(); + let symbol = symbol.unwrap(); if ident_iter.num_remaining() != 0 { return FindTypeResult::SymbolPartial{ ident_pos: identifier.position, @@ -89,7 +89,88 @@ pub(crate) fn find_type_definition<'t, 'i>( // able to match the definition's ID to an entry in the type table. let definition = types.get_base_definition(&definition_id); debug_assert!(definition.is_some()); - FindTypeResult::Found(definition.unwrap()) + FindTypeResult::Found((definition.unwrap(), ident_iter)) } } +} + +pub(crate) enum MatchPolymorphResult<'t> { + Matching, + InferAll(usize), + Mismatch{defined_type: &'t DefinedType, ident_position: InputPosition, num_specified: usize}, + NoneExpected{defined_type: &'t DefinedType, ident_position: InputPosition, num_specified: usize}, +} + +impl<'t> MatchPolymorphResult<'t> { + pub(crate) fn as_parse_error(self, heap: &Heap, module_source: &InputSource) -> Result { + match self { + MatchPolymorphResult::Matching => Ok(0), + MatchPolymorphResult::InferAll(count) => { + debug_assert!(count > 0); + Ok(count) + }, + MatchPolymorphResult::Mismatch{defined_type, ident_position, num_specified} => { + let type_identifier = heap[defined_type.ast_definition].identifier(); + let args_name = if defined_type.poly_vars.len() == 1 { + "argument" + } else { + "arguments" + }; + + return Err(ParseError2::new_error( + module_source, ident_position, + &format!( + "expected {} polymorphic {} (or none, to infer them) for the type {}, but {} were specified", + defined_type.poly_vars.len(), args_name, + &String::from_utf8_lossy(&type_identifier.value), + num_specified + ) + )) + }, + MatchPolymorphResult::NoneExpected{defined_type, ident_position, ..} => { + let type_identifier = heap[defined_type.ast_definition].identifier(); + return Err(ParseError2::new_error( + module_source, ident_position, + &format!( + "the type {} is not polymorphic", + &String::from_utf8_lossy(&type_identifier.value) + ) + )) + } + } + } +} + +/// Attempt to match the polymorphic arguments to the number of polymorphic +/// variables in the definition. +pub(crate) fn match_polymorphic_args_to_vars<'t>( + defined_type: &'t DefinedType, poly_args: Option<&[ParserTypeId]>, ident_position: InputPosition +) -> MatchPolymorphResult<'t> { + if defined_type.poly_vars.is_empty() { + // No polymorphic variables on type + if poly_args.is_some() { + return MatchPolymorphResult::NoneExpected{ + defined_type, + ident_position, + num_specified: poly_args.unwrap().len()}; + } + } else { + // Polymorphic variables on type + let has_specified = poly_args.map_or(false, |a| a.len() != 0); + if !has_specified { + // Implicitly infer all of the polymorphic arguments + return MatchPolymorphResult::InferAll(defined_type.poly_vars.len()); + } + + let num_specified = poly_args.unwrap().len(); + if num_specified != defined_type.poly_vars.len() { + return MatchPolymorphResult::Mismatch{ + defined_type, + ident_position, + num_specified, + }; + } + } + + MatchPolymorphResult::Matching } \ No newline at end of file diff --git a/src/protocol/parser/visitor_linker.rs b/src/protocol/parser/visitor_linker.rs index 9e25aca30a4dd55fef959f8625b3d29c6af509f7..e963d585b40e49ce40afb1ba59440cb4ac24a38b 100644 --- a/src/protocol/parser/visitor_linker.rs +++ b/src/protocol/parser/visitor_linker.rs @@ -1075,10 +1075,10 @@ impl ValidityAndLinkerVisitor { let mut symbolic_variant = None; for (poly_var_idx, poly_var) in poly_vars.iter().enumerate() { - if symbolic.identifier == *poly_var { + if symbolic.identifier.matches_identifier(poly_var) { // Type refers to a polymorphic variable. // TODO: @hkt Maybe allow higher-kinded types? - if !symbolic.poly_args.is_empty() { + if symbolic.identifier.get_poly_args().is_some() { return Err(ParseError2::new_error( &ctx.module.source, symbolic.identifier.position, "Polymorphic arguments to a polymorphic variable (higher-kinded types) are not allowed (yet)" @@ -1089,11 +1089,11 @@ impl ValidityAndLinkerVisitor { } if let Some(symbolic_variant) = symbolic_variant { - // Identifier points to a symbolic type + // Identifier points to a polymorphic argument (symbolic.identifier.position, symbolic_variant, 0) } else { // Must be a user-defined type, otherwise an error - let found_type = find_type_definition( + let (found_type, ident_iter) = find_type_definition( &ctx.symbols, &ctx.types, ctx.module.root_id, &symbolic.identifier ).as_parse_error(&ctx.module.source)?; @@ -1113,40 +1113,22 @@ impl ValidityAndLinkerVisitor { // the programmer did not specify the polyargs then we // assume we're going to infer all of them. Otherwise we // make sure that they match in count. - if !found_type.poly_args.is_empty() && symbolic.poly_args.is_empty() { - // All inferred - ( - symbolic.identifier.position, - SymbolicParserTypeVariant::Definition(found_type.ast_definition), - found_type.poly_args.len() - ) - } else if symbolic.poly_args.len() != found_type.poly_args.len() { - return Err(ParseError2::new_error( - &ctx.module.source, symbolic.identifier.position, - &format!( - "Expected {} polymorphic arguments (or none, to infer them), but {} were specified", - found_type.poly_args.len(), symbolic.poly_args.len() - ) - )) - } else { - // If here then the type is not polymorphic, or all - // types are properly specified by the user. - for specified_poly_arg in &symbolic.poly_args { - self.parser_type_buffer.push(*specified_poly_arg); - } - - ( - symbolic.identifier.position, - SymbolicParserTypeVariant::Definition(found_type.ast_definition), - 0 - ) - } + let (_, poly_args) = ident_iter.prev().unwrap(); + let num_to_infer = match_polymorphic_args_to_vars( + found_type, poly_args, symbolic.identifier.position + ).as_parse_error(&ctx.heap, &ctx.module.source)?; + + ( + symbolic.identifier.position, + SymbolicParserTypeVariant::Definition(found_type.ast_definition), + num_to_infer + ) } } }; - // If here then type is symbolic, perform a mutable borrow to set - // the target of the symbolic type. + // If here then type is symbolic, perform a mutable borrow (and do + // some rust shenanigans) to set the required information. for _ in 0..num_inferred_to_allocate { // TODO: @hack, not very user friendly to manually allocate // `inferred` ParserTypes with the InputPosition of the @@ -1161,8 +1143,13 @@ impl ValidityAndLinkerVisitor { } if let PTV::Symbolic(symbolic) = &mut ctx.heap[parser_type_id].variant { - for _ in 0..num_inferred_to_allocate { - symbolic.poly_args.push(self.parser_type_buffer.pop().unwrap()); + if num_inferred_to_allocate != 0 { + symbolic.poly_args2.reserve(num_inferred_to_allocate); + for _ in 0..num_inferred_to_allocate { + symbolic.poly_args2.push(self.parser_type_buffer.pop().unwrap()); + } + } else if !symbolic.identifier.poly_args.is_empty() { + symbolic.poly_args2.extend(&symbolic.identifier.poly_args) } symbolic.variant = Some(symbolic_variant); } else { @@ -1252,14 +1239,9 @@ impl ValidityAndLinkerVisitor { /// Finds a variable in the visitor's scope that must appear before the /// specified relative position within that block. - fn find_variable(&self, ctx: &Ctx, mut relative_pos: u32, identifier: &NamespacedIdentifier) -> Result { + fn find_variable(&self, ctx: &Ctx, mut relative_pos: u32, identifier: &NamespacedIdentifier2) -> Result { debug_assert!(self.cur_scope.is_some()); - debug_assert!(identifier.num_namespaces > 0); - - // TODO: Update once globals are possible as well - if identifier.num_namespaces > 1 { - todo!("Implement namespaced constant seeking") - } + debug_assert!(identifier.parts.len() == 1, "implement namespaced seeking of target associated with identifier"); // TODO: May still refer to an alias of a global symbol using a single // identifier in the namespace. @@ -1273,7 +1255,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 == *identifier { + if local.relative_pos_in_block < relative_pos && identifier.matches_identifier(&local.identifier) { return Ok(local_id.upcast()); } } @@ -1287,7 +1269,7 @@ impl ValidityAndLinkerVisitor { let definition = &ctx.heap[*definition_id]; for parameter_id in definition.parameters() { let parameter = &ctx.heap[*parameter_id]; - if parameter.identifier == *identifier { + if identifier.matches_identifier(¶meter.identifier) { return Ok(parameter_id.upcast()); } } @@ -1391,10 +1373,10 @@ impl ValidityAndLinkerVisitor { // borrowing errors fn find_symbol_of_type<'a>( &self, source: &InputSource, root_id: RootId, symbols: &SymbolTable, types: &'a TypeTable, - identifier: &NamespacedIdentifier, expected_type_class: TypeClass + identifier: &NamespacedIdentifier2, expected_type_class: TypeClass ) -> Result<&'a DefinedType, ParseError2> { // Find symbol associated with identifier - let find_result = find_type_definition(symbols, types, root_id, identifier) + let (find_result, _) = find_type_definition(symbols, types, root_id, identifier) .as_parse_error(source)?; let definition_type_class = find_result.definition.type_class(); @@ -1497,6 +1479,14 @@ impl ValidityAndLinkerVisitor { // TODO: @cleanup, merge with function below fn visit_call_poly_args(&mut self, ctx: &mut Ctx, call_id: CallExpressionId) -> VisitorResult { + // TODO: @token Revisit when tokenizer is implemented + let call_expr = &mut ctx.heap[call_id]; + if let Method::Symbolic(symbolic) = &mut call_expr.method { + if let Some(poly_args) = symbolic.identifier.get_poly_args() { + call_expr.poly_args.extend(poly_args); + } + } + let call_expr = &ctx.heap[call_id]; // Determine the polyarg signature @@ -1514,6 +1504,9 @@ impl ValidityAndLinkerVisitor { 1 } Method::Symbolic(symbolic) => { + // Retrieve type and make sure number of specified polymorphic + // arguments is correct + let definition = &ctx.heap[symbolic.definition.unwrap()]; match definition { Definition::Function(definition) => definition.poly_vars.len(), @@ -1571,9 +1564,15 @@ impl ValidityAndLinkerVisitor { } fn visit_literal_poly_args(&mut self, ctx: &mut Ctx, lit_id: LiteralExpressionId) -> VisitorResult { + // TODO: @token Revisit when tokenizer is implemented + let literal_expr = &mut ctx.heap[lit_id]; + if let Literal::Struct(literal) = &mut literal_expr.value { + literal.poly_args2.extend(&literal.identifier.poly_args); + } + let literal_expr = &ctx.heap[lit_id]; let literal_pos = literal_expr.position; - let (num_specified, num_expected) = match &literal_expr.value { + let num_poly_args_to_infer = 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 @@ -1582,58 +1581,43 @@ impl ValidityAndLinkerVisitor { unreachable!(); }, Literal::Struct(literal) => { - let definition = &ctx.heap[literal.definition.unwrap()]; - let num_expected = match definition { - Definition::Struct(definition) => definition.poly_vars.len(), - _ => { - debug_assert!(false, "expected struct literal while visiting literal poly args"); - 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) + // Retrieve type and make sure number of specified polymorphic + // arguments is correct. + let defined_type = ctx.types.get_base_definition(literal.definition.as_ref().unwrap()) + .unwrap(); + let maybe_poly_args = literal.identifier.get_poly_args(); + let num_to_infer = match_polymorphic_args_to_vars( + defined_type, maybe_poly_args, literal.identifier.position + ).as_parse_error(&ctx.heap, &ctx.module.source)?; + + // Visit all specified parser types let old_num_types = self.parser_type_buffer.len(); - self.parser_type_buffer.extend(&literal.poly_args); + self.parser_type_buffer.extend(&literal.poly_args2); 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); - (num_specified, num_expected) + num_to_infer } }; - 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: literal_pos, variant: ParserTypeVariant::Inferred - })); - } + if num_poly_args_to_infer != 0 { + for _ in 0..num_poly_args_to_infer { + self.parser_type_buffer.push(ctx.heap.alloc_parser_type(|this| ParserType{ + this, pos: literal_pos, variant: ParserTypeVariant::Inferred + })); + } - 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()); - } + let literal = match &mut ctx.heap[lit_id].value { + Literal::Struct(literal) => literal, + _ => unreachable!(), + }; + literal.poly_args2.reserve(num_poly_args_to_infer); + for _ in 0..num_poly_args_to_infer { + literal.poly_args2.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(()) diff --git a/src/protocol/tests/utils.rs b/src/protocol/tests/utils.rs index 4c15ce3e30162774258dad5a945057904ac1862b..e375b6abc0f348460a6966c94fd1a7cf152d355a 100644 --- a/src/protocol/tests/utils.rs +++ b/src/protocol/tests/utils.rs @@ -675,9 +675,9 @@ fn serialize_parser_type(buffer: &mut String, heap: &Heap, id: ParserTypeId) { }, PTV::Symbolic(symbolic) => { buffer.push_str(&String::from_utf8_lossy(&symbolic.identifier.value)); - if symbolic.poly_args.len() > 0 { + if symbolic.poly_args2.len() > 0 { buffer.push('<'); - for (poly_idx, poly_arg) in symbolic.poly_args.iter().enumerate() { + for (poly_idx, poly_arg) in symbolic.poly_args2.iter().enumerate() { if poly_idx != 0 { buffer.push(','); } serialize_parser_type(buffer, heap, *poly_arg); }