1
0
forked from M-Labs/nac3

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

View File

@ -12,6 +12,8 @@ pub enum TypeAnnotation {
// can only be CustomClassKind // can only be CustomClassKind
VirtualKind(Box<TypeAnnotation>), VirtualKind(Box<TypeAnnotation>),
TypeVarKind(Type), TypeVarKind(Type),
ListKind(Box<TypeAnnotation>),
TupleKind(Vec<TypeAnnotation>),
} }
pub fn parse_ast_to_type_annotation_kinds<T>( 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, .. } ast::ExprKind::Subscript { value, slice, .. }
if { matches!(&value.node, ast::ExprKind::Name { id, .. } if id == "virtual") } => 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())) 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, .. } => { ast::ExprKind::Subscript { value, slice, .. } => {
if let ast::ExprKind::Name { id, .. } = &value.node { 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()); return Err("keywords cannot be class name".into());
} }
let obj_id = resolver let obj_id = resolver
@ -206,6 +246,24 @@ pub fn get_type_from_type_annotation_kinds(
)?; )?;
Ok(unifier.add_ty(TypeEnum::TVirtual { ty })) 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 }))
}
} }
} }