forked from M-Labs/nac3
1
0
Fork 0

nac3core: toplevel cleanup and add list and tuple support

This commit is contained in:
ychenfo 2021-08-30 14:04:32 +08:00
parent 40e58d02ed
commit 82c2edcf8d
2 changed files with 67 additions and 24 deletions

View File

@ -99,7 +99,6 @@ impl Default for TopLevelComposer {
impl TopLevelComposer {
/// return a composer and things to make a "primitive" symbol resolver, so that the symbol
/// resolver can later figure out primitive type definitions when passed a primitive type name
// TODO: add list and tuples?
pub fn new() -> Self {
let primitives = Self::make_primitives();
@ -397,15 +396,13 @@ impl TopLevelComposer {
// first, only push direct parent into the list
for (class_def, class_ast) in self.definition_ast_list.iter_mut() {
let mut class_def = class_def.write();
let (class_bases, class_ancestors, class_resolver, class_id, class_type_vars) = {
if let TopLevelDef::Class { ancestors, resolver, object_id, type_vars, .. } =
class_def.deref_mut()
{
let (class_bases, class_ancestors, class_resolver) = {
if let TopLevelDef::Class { ancestors, resolver, .. } = class_def.deref_mut() {
if let Some(ast::Located {
node: ast::StmtKind::ClassDef { bases, .. }, ..
}) = class_ast
{
(bases, ancestors, resolver, *object_id, type_vars)
(bases, ancestors, resolver)
} else {
unreachable!("must be both class")
}
@ -453,10 +450,6 @@ impl TopLevelComposer {
return Err("class base declaration can only be custom class".into());
}
}
// TODO: ancestors should include all bases, need to rewrite
// push self to the ancestors
// class_ancestors.push(make_self_type_annotation(&temp_def_list, class_id)?)
}
// second get all ancestors
@ -531,9 +524,6 @@ impl TopLevelComposer {
)?
}
// base class methods add and check
// TODO:
// unification of previously assigned typevar
for (ty, def) in type_var_to_concrete_def {
let target_ty =
@ -629,7 +619,6 @@ impl TopLevelComposer {
&type_annotation,
)?;
// TODO: default value?
Ok(FuncArg {
name: x.node.arg.clone(),
ty,
@ -867,14 +856,10 @@ impl TopLevelComposer {
// handle the class type var and the method type var
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)?;
if let Some(prev_ty) = method_var_map.insert(id, ty) {
// if already in the list, make sure they are the same?
assert_eq!(prev_ty, ty);
}
} else {
unreachable!("must be type var annotation");
let id = get_var_id(ty, unifier)?;
if let Some(prev_ty) = method_var_map.insert(id, ty) {
// if already in the list, make sure they are the same?
assert_eq!(prev_ty, ty);
}
} else {
unreachable!("must be type var annotation");

View File

@ -12,6 +12,8 @@ pub enum TypeAnnotation {
// can only be CustomClassKind
VirtualKind(Box<TypeAnnotation>),
TypeVarKind(Type),
ListKind(Box<TypeAnnotation>),
TupleKind(Vec<TypeAnnotation>),
}
pub fn parse_ast_to_type_annotation_kinds<T>(
@ -55,7 +57,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
}
},
// TODO: subscript or call for virtual?
// virtual
ast::ExprKind::Subscript { value, slice, .. }
if { matches!(&value.node, ast::ExprKind::Name { id, .. } if id == "virtual") } =>
{
@ -72,9 +74,47 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
Ok(TypeAnnotation::VirtualKind(def.into()))
}
// list
ast::ExprKind::Subscript { value, slice, .. }
if { matches!(&value.node, ast::ExprKind::Name { id, .. } if id == "list") } =>
{
let def_ann = parse_ast_to_type_annotation_kinds(
resolver,
top_level_defs,
unifier,
primitives,
slice.as_ref(),
)?;
Ok(TypeAnnotation::ListKind(def_ann.into()))
}
// tuple
ast::ExprKind::Subscript { value, slice, .. }
if { matches!(&value.node, ast::ExprKind::Name { id, .. } if id == "tuple") } =>
{
if let ast::ExprKind::Tuple { elts, .. } = &slice.node {
let type_annotations = elts
.iter()
.map(|e| {
parse_ast_to_type_annotation_kinds(
resolver,
top_level_defs,
unifier,
primitives,
e,
)
})
.collect::<Result<Vec<_>, _>>()?;
Ok(TypeAnnotation::TupleKind(type_annotations))
} else {
Err("Expect multiple elements for tuple".into())
}
}
// custom class
ast::ExprKind::Subscript { value, slice, .. } => {
if let ast::ExprKind::Name { id, .. } = &value.node {
if vec!["virtual", "Generic"].contains(&id.as_str()) {
if vec!["virtual", "Generic", "list", "tuple"].contains(&id.as_str()) {
return Err("keywords cannot be class name".into());
}
let obj_id = resolver
@ -206,6 +246,24 @@ pub fn get_type_from_type_annotation_kinds(
)?;
Ok(unifier.add_ty(TypeEnum::TVirtual { ty }))
}
TypeAnnotation::ListKind(ty) => {
let ty = get_type_from_type_annotation_kinds(
top_level_defs,
unifier,
primitives,
ty.as_ref(),
)?;
Ok(unifier.add_ty(TypeEnum::TList { ty }))
}
TypeAnnotation::TupleKind(tys) => {
let tys = tys
.iter()
.map(|x| {
get_type_from_type_annotation_kinds(top_level_defs, unifier, primitives, x)
})
.collect::<Result<Vec<_>, _>>()?;
Ok(unifier.add_ty(TypeEnum::TTuple { ty: tys }))
}
}
}