nac3core: top level clean up and fix ancestors analysis

This commit is contained in:
ychenfo 2021-08-30 22:46:50 +08:00
parent 098bd1e6e6
commit 4a9593efa3
3 changed files with 42 additions and 41 deletions

View File

@ -103,18 +103,26 @@ impl TopLevelComposer {
result result
} }
/// should only be called when finding all ancestors, so panic when wrong
fn get_parent( fn get_parent(
child: &TypeAnnotation, child: &TypeAnnotation,
temp_def_list: &[Arc<RwLock<TopLevelDef>>], temp_def_list: &[Arc<RwLock<TopLevelDef>>],
) -> Option<TypeAnnotation> { ) -> Option<TypeAnnotation> {
let child_id = let child_id = if let TypeAnnotation::CustomClassKind { id, .. } = child {
if let TypeAnnotation::CustomClassKind { id, .. } = child { *id } else { return None }; *id
} else {
unreachable!("should be class type annotation")
};
let child_def = temp_def_list.get(child_id.0).unwrap(); let child_def = temp_def_list.get(child_id.0).unwrap();
let child_def = child_def.read(); let child_def = child_def.read();
if let TopLevelDef::Class { ancestors, .. } = &*child_def { if let TopLevelDef::Class { ancestors, .. } = &*child_def {
Some(ancestors[0].clone()) if !ancestors.is_empty() {
Some(ancestors[0].clone())
} else {
None
}
} else { } else {
None unreachable!("child must be top level class def")
} }
} }
@ -162,4 +170,13 @@ impl TopLevelComposer {
_ => false, _ => false,
} }
} }
/// get the var_id of a given TVar type
pub fn get_var_id(var_ty: Type, unifier: &mut Unifier) -> Result<u32, String> {
if let TypeEnum::TVar { id, .. } = unifier.get_ty(var_ty).as_ref() {
Ok(*id)
} else {
Err("not type var".to_string())
}
}
} }

View File

@ -176,7 +176,7 @@ impl TopLevelComposer {
Arc::new(RwLock::new(Self::make_top_level_class_def( Arc::new(RwLock::new(Self::make_top_level_class_def(
class_def_id, class_def_id,
resolver.clone(), resolver.clone(),
name.as_str(), name,
))), ))),
None, None,
); );
@ -233,7 +233,7 @@ impl TopLevelComposer {
// move the ast to the entry of the class in the ast_list // move the ast to the entry of the class in the ast_list
class_def_ast.1 = Some(ast); class_def_ast.1 = Some(ast);
// get the methods into the class_def // get the methods into the top level class_def
for (name, _, id, ty) in &class_method_name_def_ids { for (name, _, id, ty) in &class_method_name_def_ids {
let mut class_def = class_def_ast.0.write(); let mut class_def = class_def_ast.0.write();
if let TopLevelDef::Class { methods, .. } = class_def.deref_mut() { if let TopLevelDef::Class { methods, .. } = class_def.deref_mut() {
@ -271,7 +271,7 @@ impl TopLevelComposer {
self.definition_ast_list.push(( self.definition_ast_list.push((
RwLock::new(Self::make_top_level_function_def( RwLock::new(Self::make_top_level_function_def(
name.into(), name.into(),
// unify with correct type later // dummy here, unify with correct type later
self.unifier.get_fresh_var().0, self.unifier.get_fresh_var().0,
resolver, resolver,
)) ))
@ -336,13 +336,13 @@ impl TopLevelComposer {
return Err("Only single Generic[...] can be in bases".into()); return Err("Only single Generic[...] can be in bases".into());
} }
let mut type_var_list: Vec<&ast::Expr<()>> = vec![]; let type_var_list: Vec<&ast::Expr<()>>;
// if `class A(Generic[T, V, G])` // if `class A(Generic[T, V, G])`
if let ast::ExprKind::Tuple { elts, .. } = &slice.node { if let ast::ExprKind::Tuple { elts, .. } = &slice.node {
type_var_list.extend(elts.iter()); type_var_list = elts.iter().collect_vec();
// `class A(Generic[T])` // `class A(Generic[T])`
} else { } else {
type_var_list.push(slice.deref()); type_var_list = vec![slice.deref()];
} }
// parse the type vars // parse the type vars
@ -454,39 +454,32 @@ impl TopLevelComposer {
// second, get all ancestors // second, get all ancestors
let mut ancestors_store: HashMap<DefinitionId, Vec<TypeAnnotation>> = Default::default(); let mut ancestors_store: HashMap<DefinitionId, Vec<TypeAnnotation>> = Default::default();
for (class_def, class_ast) in self.definition_ast_list.iter_mut() { for (class_def, _) in self.definition_ast_list.iter_mut() {
let mut class_def = class_def.write(); let mut class_def = class_def.write();
let (class_ancestors, class_id) = { let (class_ancestors, class_id) = {
if let TopLevelDef::Class { ancestors, object_id, .. } = class_def.deref_mut() { if let TopLevelDef::Class { ancestors, object_id, .. } = class_def.deref_mut() {
if let Some(ast::Located { node: ast::StmtKind::ClassDef { .. }, .. }) = (ancestors, *object_id)
class_ast
{
(ancestors, *object_id)
} else {
unreachable!("must be both class")
}
} else { } else {
continue; continue;
} }
}; };
ancestors_store.insert( ancestors_store.insert(
class_id, class_id,
Self::get_all_ancestors_helper(&class_ancestors[0], temp_def_list.as_slice()), // if class has direct parents, get all ancestors of its parents. Else just empty
if class_ancestors.is_empty() {
vec![]
} else {
Self::get_all_ancestors_helper(&class_ancestors[0], temp_def_list.as_slice())
},
); );
} }
// insert the ancestors to the def list // insert the ancestors to the def list
for (class_def, class_ast) in self.definition_ast_list.iter_mut() { for (class_def, _) in self.definition_ast_list.iter_mut() {
let mut class_def = class_def.write(); let mut class_def = class_def.write();
let (class_ancestors, class_id) = { let (class_ancestors, class_id) = {
if let TopLevelDef::Class { ancestors, object_id, .. } = class_def.deref_mut() { if let TopLevelDef::Class { ancestors, object_id, .. } = class_def.deref_mut() {
if let Some(ast::Located { node: ast::StmtKind::ClassDef { .. }, .. }) = (ancestors, *object_id)
class_ast
{
(ancestors, *object_id)
} else {
unreachable!("must be both class")
}
} else { } else {
continue; continue;
} }
@ -495,7 +488,7 @@ impl TopLevelComposer {
let ans = ancestors_store.get_mut(&class_id).unwrap(); let ans = ancestors_store.get_mut(&class_id).unwrap();
class_ancestors.append(ans); class_ancestors.append(ans);
// insert self type annotation // insert self type annotation to the front of the vector to maintain the order
class_ancestors class_ancestors
.insert(0, make_self_type_annotation(temp_def_list.as_slice(), class_id)?); .insert(0, make_self_type_annotation(temp_def_list.as_slice(), class_id)?);
} }
@ -609,7 +602,7 @@ impl TopLevelComposer {
.into_iter() .into_iter()
.map(|x| -> Result<(u32, Type), String> { .map(|x| -> Result<(u32, Type), String> {
if let TypeAnnotation::TypeVarKind(ty) = x { if let TypeAnnotation::TypeVarKind(ty) = x {
Ok((get_var_id(ty, unifier)?, ty)) Ok((Self::get_var_id(ty, unifier)?, ty))
} else { } else {
unreachable!("must be type var annotation kind") unreachable!("must be type var annotation kind")
} }
@ -657,7 +650,7 @@ impl TopLevelComposer {
.into_iter() .into_iter()
.map(|x| -> Result<(u32, Type), String> { .map(|x| -> Result<(u32, Type), String> {
if let TypeAnnotation::TypeVarKind(ty) = x { if let TypeAnnotation::TypeVarKind(ty) = x {
Ok((get_var_id(ty, unifier)?, ty)) Ok((Self::get_var_id(ty, unifier)?, ty))
} else { } else {
unreachable!("must be type var here") unreachable!("must be type var here")
} }
@ -799,7 +792,7 @@ impl TopLevelComposer {
// handle the class type var and the method type var // handle the class type var and the method type var
for type_var_within in type_vars_within { for type_var_within in type_vars_within {
if let TypeAnnotation::TypeVarKind(ty) = type_var_within { if let TypeAnnotation::TypeVarKind(ty) = type_var_within {
let id = get_var_id(ty, unifier)?; let id = Self::get_var_id(ty, unifier)?;
if let Some(prev_ty) = method_var_map.insert(id, ty) { if let Some(prev_ty) = method_var_map.insert(id, ty) {
// if already in the list, make sure they are the same? // if already in the list, make sure they are the same?
assert_eq!(prev_ty, ty); assert_eq!(prev_ty, ty);
@ -860,7 +853,7 @@ impl TopLevelComposer {
// handle the class type var and the method type var // handle the class type var and the method type var
for type_var_within in type_vars_within { for type_var_within in type_vars_within {
if let TypeAnnotation::TypeVarKind(ty) = type_var_within { if let TypeAnnotation::TypeVarKind(ty) = type_var_within {
let id = get_var_id(ty, unifier)?; let id = Self::get_var_id(ty, unifier)?;
if let Some(prev_ty) = method_var_map.insert(id, ty) { if let Some(prev_ty) = method_var_map.insert(id, ty) {
// if already in the list, make sure they are the same? // if already in the list, make sure they are the same?
assert_eq!(prev_ty, ty); assert_eq!(prev_ty, ty);

View File

@ -323,12 +323,3 @@ pub fn get_type_var_contained_in_type_annotation(ann: &TypeAnnotation) -> Vec<Ty
} }
result result
} }
/// get the var_id of a given TVar type
pub fn get_var_id(var_ty: Type, unifier: &mut Unifier) -> Result<u32, String> {
if let TypeEnum::TVar { id, .. } = unifier.get_ty(var_ty).as_ref() {
Ok(*id)
} else {
Err("not type var".to_string())
}
}