diff --git a/schala-lang/language/src/symbol_table.rs b/schala-lang/language/src/symbol_table.rs index b06edf0..c2a83b9 100644 --- a/schala-lang/language/src/symbol_table.rs +++ b/schala-lang/language/src/symbol_table.rs @@ -77,11 +77,12 @@ pub enum SymbolSpec { Func(Vec), DataConstructor { index: usize, - type_name: Rc, + type_name: TypeName, type_args: Vec>, }, RecordConstructor { - fields: HashMap, Rc> + members: HashMap, TypeName>, + type_name: TypeName, }, Binding } @@ -92,7 +93,7 @@ impl fmt::Display for SymbolSpec { match self { Func(type_names) => write!(f, "Func({:?})", type_names), DataConstructor { index, type_name, type_args } => write!(f, "DataConstructor(idx: {})({:?} -> {})", index, type_args, type_name), - RecordConstructor { fields: _fields } => write!(f, "RecordConstructor( )"), + RecordConstructor { type_name, ..} => write!(f, "RecordConstructor( -> {})", type_name), Binding => write!(f, "Binding"), } } @@ -180,7 +181,7 @@ impl SymbolTable { fn add_type_decl(&mut self, type_name: &TypeSingletonName, body: &TypeBody, _mutable: &bool, scope_name_stack: &mut Vec) -> Result<(), String> { use crate::ast::{TypeIdentifier, Variant}; let TypeBody(variants) = body; - let TypeSingletonName { name, .. } = type_name; + let ref type_name = type_name.name; //scope_name_stack.push(name.clone()); //TODO adding this makes variants scoped under their //type name and breaks a lot of things - don't add it until importing names works //TODO figure out why _params isn't being used here @@ -189,28 +190,44 @@ impl SymbolTable { Variant::UnitStruct(variant_name) => { let spec = SymbolSpec::DataConstructor { index, - type_name: name.clone(), + type_name: type_name.clone(), type_args: vec![], }; self.add_new_symbol(variant_name, scope_name_stack, spec); }, Variant::TupleStruct(variant_name, tuple_members) => { + //TODO fix the notion of a tuple type let type_args = tuple_members.iter().map(|type_name| match type_name { TypeIdentifier::Singleton(TypeSingletonName { name, ..}) => name.clone(), TypeIdentifier::Tuple(_) => unimplemented!(), }).collect(); let spec = SymbolSpec::DataConstructor { index, - type_name: name.clone(), + type_name: type_name.clone(), type_args }; self.add_new_symbol(variant_name, scope_name_stack, spec); }, //TODO if there is only one variant, and it is a record, it doesn't need to have an //explicit name - Variant::Record { name, members: _members } => { - let fields = HashMap::new(); - let spec = SymbolSpec::RecordConstructor { fields }; + Variant::Record { name, members: defined_members } => { + let mut members = HashMap::new(); + let mut duplicate_member_definitions = Vec::new(); + for (member_name, member_type) in defined_members { + match members.entry(member_name.clone()) { + Entry::Occupied(_) => duplicate_member_definitions.push(member_name.clone()), + Entry::Vacant(v) => { + v.insert(match member_type { + TypeIdentifier::Singleton(TypeSingletonName { name, ..}) => name.clone(), + TypeIdentifier::Tuple(_) => unimplemented!(), + }); + } + } + } + if duplicate_member_definitions.len() != 0 { + return Err(format!("Duplicate member(s) in definition of type {}: {:?}", type_name, duplicate_member_definitions)); + } + let spec = SymbolSpec::RecordConstructor { type_name: type_name.clone(), members }; self.add_new_symbol(name, scope_name_stack, spec); }, }