diff --git a/schala-lang/src/symbol_table/fqsn.rs b/schala-lang/src/symbol_table/fqsn.rs index 5c3c784..2e1fdc8 100644 --- a/schala-lang/src/symbol_table/fqsn.rs +++ b/schala-lang/src/symbol_table/fqsn.rs @@ -17,6 +17,12 @@ impl Fqsn { Fqsn { scopes: v } } + pub fn extend(&self, new_item: &str) -> Self { + let mut new = self.clone(); + new.scopes.push(ScopeSegment::Name(Rc::new(new_item.to_string()))); + new + } + #[allow(dead_code)] pub fn from_strs(strs: &[&str]) -> Fqsn { let mut scopes = vec![]; diff --git a/schala-lang/src/symbol_table/mod.rs b/schala-lang/src/symbol_table/mod.rs index 2f07049..dc239fc 100644 --- a/schala-lang/src/symbol_table/mod.rs +++ b/schala-lang/src/symbol_table/mod.rs @@ -32,12 +32,11 @@ pub type DefId = Id; pub enum SymbolError { DuplicateName { prev_name: Fqsn, location: Location }, DuplicateVariant { type_fqsn: Fqsn, name: String }, - DuplicateRecord { type_name: Fqsn, location: Location, member: String }, + DuplicateRecord { type_fqsn: Fqsn, location: Location, record: String, member: String }, UnknownAnnotation { name: String }, BadAnnotation { name: String, msg: String }, } -#[allow(dead_code)] #[derive(Debug)] struct NameSpec { location: Location, @@ -52,7 +51,10 @@ enum NameKind { } #[derive(Debug)] -struct TypeKind; +enum TypeKind { + Function, + Constructor, +} /// Keeps track of what names were used in a given namespace. struct NameTable { @@ -154,7 +156,7 @@ impl SymbolTable { fn add_symbol(&mut self, id: &ItemId, fqsn: Fqsn, spec: SymbolSpec) { let def_id = self.def_id_store.fresh(); let local_name = fqsn.last_elem(); - let symbol = Rc::new( Symbol { fully_qualified_name: fqsn.clone(), local_name, spec, def_id }); + let symbol = Rc::new(Symbol { fully_qualified_name: fqsn.clone(), local_name, spec, def_id }); self.symbol_trie.insert(&fqsn, def_id); self.id_to_def.insert(*id, def_id); self.def_to_symbol.insert(def_id, symbol); diff --git a/schala-lang/src/symbol_table/populator.rs b/schala-lang/src/symbol_table/populator.rs index bed4ee0..815ac1c 100644 --- a/schala-lang/src/symbol_table/populator.rs +++ b/schala-lang/src/symbol_table/populator.rs @@ -71,10 +71,12 @@ impl<'a> SymbolTablePopulator<'a> { scope_stack.pop(); output } - Declaration::TypeDecl { name, body, mutable } => - self.add_type_members(name, body, mutable, location, scope_stack), + Declaration::TypeDecl { name, body, mutable } => { + let type_fqsn = Fqsn::from_scope_stack(scope_stack, name.name.clone()); + self.add_type_members(name, body, mutable, location, type_fqsn) + } - /* + /* Declaration::Impl { type_name, body, .. } => { }, @@ -102,7 +104,9 @@ impl<'a> SymbolTablePopulator<'a> { self.table .fq_names .register(fq_function.clone(), NameSpec { location, kind: NameKind::Function })?; - self.table.types.register(fq_function.clone(), NameSpec { location, kind: TypeKind })?; + self.table + .types + .register(fq_function.clone(), NameSpec { location, kind: TypeKind::Function })?; self.add_symbol(id, fq_function, SymbolSpec::Func { method: None }); } @@ -112,13 +116,15 @@ impl<'a> SymbolTablePopulator<'a> { self.table .fq_names .register(fq_function.clone(), NameSpec { location, kind: NameKind::Function })?; - self.table.types.register(fq_function.clone(), NameSpec { location, kind: TypeKind })?; + self.table + .types + .register(fq_function.clone(), NameSpec { location, kind: TypeKind::Function })?; self.add_symbol(id, fq_function, SymbolSpec::Func { method: None }); } StatementKind::Declaration(Declaration::TypeDecl { name, .. }) => { let fq_type = Fqsn::from_scope_stack(scope_stack, name.name.clone()); - self.table.types.register(fq_type, NameSpec { location, kind: TypeKind })?; + self.table.types.register(fq_type, NameSpec { location, kind: TypeKind::Constructor })?; } StatementKind::Declaration(Declaration::Binding { name, .. }) => { let fq_binding = Fqsn::from_scope_stack(scope_stack, name.clone()); @@ -200,7 +206,7 @@ impl<'a> SymbolTablePopulator<'a> { type_body: &TypeBody, _mutable: &bool, location: Location, - scope_stack: &mut Vec, + type_fqsn: Fqsn, ) -> Vec { let (variants, immediate_variant) = match type_body { TypeBody::Variants(variants) => (variants.clone(), false), @@ -213,10 +219,6 @@ impl<'a> SymbolTablePopulator<'a> { true, ), }; - let type_fqsn = Fqsn::from_scope_stack(scope_stack, type_name.name.clone()); - - let new_scope = ScopeSegment::Name(type_name.name.clone()); - scope_stack.push(new_scope); // Check for duplicates before registering any types with the TypeContext let mut seen_variants = HashSet::new(); @@ -232,15 +234,15 @@ impl<'a> SymbolTablePopulator<'a> { seen_variants.insert(variant.name.clone()); if let VariantKind::Record(ref members) = variant.kind { - let variant_name = Fqsn::from_scope_stack(scope_stack.as_ref(), variant.name.clone()); let mut seen_members = HashMap::new(); for (member_name, _) in members.iter() { match seen_members.entry(member_name.as_ref()) { Entry::Occupied(o) => { let location = *o.get(); errors.push(SymbolError::DuplicateRecord { - type_name: variant_name.clone(), + type_fqsn: type_fqsn.clone(), location, + record: variant.name.as_ref().to_string(), member: member_name.as_ref().to_string(), }); } @@ -259,11 +261,11 @@ impl<'a> SymbolTablePopulator<'a> { let mut type_builder = TypeBuilder::new(type_name.name.as_ref()); - let mut fqsn_id_map = HashMap::new(); + let mut variant_name_map = HashMap::new(); for variant in variants.iter() { let Variant { name, kind, id } = variant; - fqsn_id_map.insert(Fqsn::from_scope_stack(scope_stack.as_ref(), name.clone()), id); + variant_name_map.insert(name.clone(), id); let mut variant_builder = VariantBuilder::new(name.as_ref()); match kind { @@ -287,30 +289,23 @@ impl<'a> SymbolTablePopulator<'a> { // This index is guaranteed to be the correct tag for (index, variant) in type_definition.variants.iter().enumerate() { - let fqsn = Fqsn::from_scope_stack(scope_stack.as_ref(), Rc::new(variant.name.to_string())); - let id = fqsn_id_map.get(&fqsn).unwrap(); + let id = variant_name_map.get(&variant.name).unwrap(); let tag = index as u32; let spec = match &variant.members { type_inference::VariantMembers::Unit => SymbolSpec::DataConstructor { tag, type_id }, type_inference::VariantMembers::Tuple(..) => SymbolSpec::DataConstructor { tag, type_id }, type_inference::VariantMembers::Record(..) => SymbolSpec::RecordConstructor { tag, type_id }, }; - self.table.add_symbol(id, fqsn, spec); + self.table.add_symbol(id, type_fqsn.extend(&variant.name), spec); } if immediate_variant { let variant = &type_definition.variants[0]; - let fqsn = Fqsn::from_scope_stack(scope_stack.as_ref(), Rc::new(variant.name.to_string())); - let id = fqsn_id_map.get(&fqsn).unwrap(); - let abbrev_fqsn = Fqsn::from_scope_stack( - scope_stack[0..scope_stack.len() - 1].as_ref(), - Rc::new(variant.name.to_string()), - ); + let id = variant_name_map.get(&variant.name).unwrap(); let spec = SymbolSpec::RecordConstructor { tag: 0, type_id }; - self.table.add_symbol(id, abbrev_fqsn, spec); + self.table.add_symbol(id, type_fqsn, spec); } - scope_stack.pop(); vec![] } } diff --git a/schala-lang/src/symbol_table/test.rs b/schala-lang/src/symbol_table/test.rs index 2d7bfab..33c3844 100644 --- a/schala-lang/src/symbol_table/test.rs +++ b/schala-lang/src/symbol_table/test.rs @@ -263,11 +263,11 @@ fn duplicate_struct_members() { "#; let (_, output) = add_symbols(source); - let errs = output.unwrap_err(); + let errs = dbg!(output.unwrap_err()); assert_matches!(&errs[..], [ SymbolError::DuplicateRecord { - type_name, member, ..}, - ] if type_name == &Fqsn::from_strs(&["Tarak", "Tarak"]) && member == "mets" + type_fqsn, member, record, ..}, + ] if type_fqsn == &Fqsn::from_strs(&["Tarak"]) && member == "mets" && record == "Tarak" ); }