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>),
|
Func(Vec<TypeName>),
|
||||||
DataConstructor {
|
DataConstructor {
|
||||||
index: usize,
|
index: usize,
|
||||||
type_name: Rc<String>,
|
type_name: TypeName,
|
||||||
type_args: Vec<Rc<String>>,
|
type_args: Vec<Rc<String>>,
|
||||||
},
|
},
|
||||||
RecordConstructor {
|
RecordConstructor {
|
||||||
fields: HashMap<Rc<String>, Rc<String>>
|
members: HashMap<Rc<String>, TypeName>,
|
||||||
|
type_name: TypeName,
|
||||||
},
|
},
|
||||||
Binding
|
Binding
|
||||||
}
|
}
|
||||||
@ -92,7 +93,7 @@ impl fmt::Display for SymbolSpec {
|
|||||||
match self {
|
match self {
|
||||||
Func(type_names) => write!(f, "Func({:?})", type_names),
|
Func(type_names) => write!(f, "Func({:?})", type_names),
|
||||||
DataConstructor { index, type_name, type_args } => write!(f, "DataConstructor(idx: {})({:?} -> {})", index, type_args, type_name),
|
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"),
|
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> {
|
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};
|
use crate::ast::{TypeIdentifier, Variant};
|
||||||
let TypeBody(variants) = body;
|
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
|
//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
|
//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
|
//TODO figure out why _params isn't being used here
|
||||||
@ -189,28 +190,44 @@ impl SymbolTable {
|
|||||||
Variant::UnitStruct(variant_name) => {
|
Variant::UnitStruct(variant_name) => {
|
||||||
let spec = SymbolSpec::DataConstructor {
|
let spec = SymbolSpec::DataConstructor {
|
||||||
index,
|
index,
|
||||||
type_name: name.clone(),
|
type_name: type_name.clone(),
|
||||||
type_args: vec![],
|
type_args: vec![],
|
||||||
};
|
};
|
||||||
self.add_new_symbol(variant_name, scope_name_stack, spec);
|
self.add_new_symbol(variant_name, scope_name_stack, spec);
|
||||||
},
|
},
|
||||||
Variant::TupleStruct(variant_name, tuple_members) => {
|
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 {
|
let type_args = tuple_members.iter().map(|type_name| match type_name {
|
||||||
TypeIdentifier::Singleton(TypeSingletonName { name, ..}) => name.clone(),
|
TypeIdentifier::Singleton(TypeSingletonName { name, ..}) => name.clone(),
|
||||||
TypeIdentifier::Tuple(_) => unimplemented!(),
|
TypeIdentifier::Tuple(_) => unimplemented!(),
|
||||||
}).collect();
|
}).collect();
|
||||||
let spec = SymbolSpec::DataConstructor {
|
let spec = SymbolSpec::DataConstructor {
|
||||||
index,
|
index,
|
||||||
type_name: name.clone(),
|
type_name: type_name.clone(),
|
||||||
type_args
|
type_args
|
||||||
};
|
};
|
||||||
self.add_new_symbol(variant_name, scope_name_stack, spec);
|
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
|
//TODO if there is only one variant, and it is a record, it doesn't need to have an
|
||||||
//explicit name
|
//explicit name
|
||||||
Variant::Record { name, members: _members } => {
|
Variant::Record { name, members: defined_members } => {
|
||||||
let fields = HashMap::new();
|
let mut members = HashMap::new();
|
||||||
let spec = SymbolSpec::RecordConstructor { fields };
|
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);
|
self.add_new_symbol(name, scope_name_stack, spec);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user