Handle records more properly in symbol table
This commit is contained in:
parent
a600d34712
commit
d9eca8ffb3
@ -77,11 +77,12 @@ pub enum SymbolSpec {
|
||||
Func(Vec<TypeName>),
|
||||
DataConstructor {
|
||||
index: usize,
|
||||
type_name: Rc<String>,
|
||||
type_name: TypeName,
|
||||
type_args: Vec<Rc<String>>,
|
||||
},
|
||||
RecordConstructor {
|
||||
fields: HashMap<Rc<String>, Rc<String>>
|
||||
members: HashMap<Rc<String>, 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( <fields> )"),
|
||||
RecordConstructor { type_name, ..} => write!(f, "RecordConstructor(<members> -> {})", 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<ScopeSegment>) -> 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);
|
||||
},
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user