symbol_resolver: fixed type variable handling

This commit is contained in:
pca006132 2021-08-12 10:25:32 +08:00
parent de8b67b605
commit d46a4b2d38
2 changed files with 42 additions and 25 deletions

View File

@ -22,19 +22,22 @@ pub enum SymbolValue {
} }
pub trait SymbolResolver { pub trait SymbolResolver {
// get type of type variable identifier or top-level function type
fn get_symbol_type( fn get_symbol_type(
&self, &self,
unifier: &mut Unifier, unifier: &mut Unifier,
primitives: &PrimitiveStore, primitives: &PrimitiveStore,
str: &str, str: &str,
) -> Option<Type>; ) -> Option<Type>;
fn get_identifier_def(&self, str: &str) -> DefinitionId; // get the top-level definition of identifiers
fn get_identifier_def(&self, str: &str) -> Option<DefinitionId>;
fn get_symbol_value(&self, str: &str) -> Option<SymbolValue>; fn get_symbol_value(&self, str: &str) -> Option<SymbolValue>;
fn get_symbol_location(&self, str: &str) -> Option<Location>; fn get_symbol_location(&self, str: &str) -> Option<Location>;
// handle function call etc. // handle function call etc.
} }
impl dyn SymbolResolver { impl dyn SymbolResolver {
// convert type annotation into type
pub fn parse_type_annotation<T>( pub fn parse_type_annotation<T>(
&self, &self,
top_level: &TopLevelContext, top_level: &TopLevelContext,
@ -52,29 +55,41 @@ impl dyn SymbolResolver {
"None" => Ok(primitives.none), "None" => Ok(primitives.none),
x => { x => {
let obj_id = self.get_identifier_def(x); let obj_id = self.get_identifier_def(x);
let defs = top_level.definitions.read(); if let Some(obj_id) = obj_id {
let def = defs[obj_id.0].read(); let defs = top_level.definitions.read();
if let TopLevelDef::Class { fields, methods, type_vars, .. } = &*def { let def = defs[obj_id.0].read();
if !type_vars.is_empty() { if let TopLevelDef::Class { fields, methods, type_vars, .. } = &*def {
return Err(format!( if !type_vars.is_empty() {
"Unexpected number of type parameters: expected {} but got 0", return Err(format!(
type_vars.len() "Unexpected number of type parameters: expected {} but got 0",
)); type_vars.len()
));
}
let fields = RefCell::new(
chain(
fields.iter().map(|(k, v)| (k.clone(), *v)),
methods.iter().map(|(k, v, _)| (k.clone(), *v)),
)
.collect(),
);
Ok(unifier.add_ty(TypeEnum::TObj {
obj_id,
fields,
params: Default::default(),
}))
} else {
Err("Cannot use function name as type".into())
} }
let fields = RefCell::new(
chain(
fields.iter().map(|(k, v)| (k.clone(), *v)),
methods.iter().map(|(k, v, _)| (k.clone(), *v)),
)
.collect(),
);
Ok(unifier.add_ty(TypeEnum::TObj {
obj_id,
fields,
params: Default::default(),
}))
} else { } else {
Err("Cannot use function name as type".into()) // it could be a type variable
let ty = self
.get_symbol_type(unifier, primitives, x)
.ok_or_else(|| "Cannot use function name as type".to_owned())?;
if let TypeEnum::TVar { .. } = &*unifier.get_ty(ty) {
Ok(ty)
} else {
Err(format!("Unknown type annotation {}", x))
}
} }
} }
}, },
@ -95,7 +110,9 @@ impl dyn SymbolResolver {
vec![self.parse_type_annotation(top_level, unifier, primitives, slice)?] vec![self.parse_type_annotation(top_level, unifier, primitives, slice)?]
}; };
let obj_id = self.get_identifier_def(id); let obj_id = self
.get_identifier_def(id)
.ok_or_else(|| format!("Unknown type annotation {}", id))?;
let defs = top_level.definitions.read(); let defs = top_level.definitions.read();
let def = defs[obj_id.0].read(); let def = defs[obj_id.0].read();
if let TopLevelDef::Class { fields, methods, type_vars, .. } = &*def { if let TopLevelDef::Class { fields, methods, type_vars, .. } = &*def {

View File

@ -28,8 +28,8 @@ impl SymbolResolver for Resolver {
unimplemented!() unimplemented!()
} }
fn get_identifier_def(&self, id: &str) -> DefinitionId { fn get_identifier_def(&self, id: &str) -> Option<DefinitionId> {
self.id_to_def.get(id).cloned().unwrap() self.id_to_def.get(id).cloned()
} }
} }