Some cleanup around type registration
This commit is contained in:
parent
88dfa87e85
commit
d6c5cd100b
@ -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![];
|
||||
|
@ -32,12 +32,11 @@ pub type DefId = Id<DefItem>;
|
||||
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<K> {
|
||||
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<K> {
|
||||
|
@ -71,8 +71,10 @@ 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<ScopeSegment>,
|
||||
type_fqsn: Fqsn,
|
||||
) -> Vec<SymbolError> {
|
||||
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![]
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user