From 82c2edcf8d1574cad0ceb67d80905cb5f1a0ebfd Mon Sep 17 00:00:00 2001 From: ychenfo Date: Mon, 30 Aug 2021 14:04:32 +0800 Subject: [PATCH] nac3core: toplevel cleanup and add list and tuple support --- nac3core/src/toplevel/mod.rs | 29 +++-------- nac3core/src/toplevel/type_annotation.rs | 62 +++++++++++++++++++++++- 2 files changed, 67 insertions(+), 24 deletions(-) diff --git a/nac3core/src/toplevel/mod.rs b/nac3core/src/toplevel/mod.rs index e14772b0c..84b5cb996 100644 --- a/nac3core/src/toplevel/mod.rs +++ b/nac3core/src/toplevel/mod.rs @@ -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"); diff --git a/nac3core/src/toplevel/type_annotation.rs b/nac3core/src/toplevel/type_annotation.rs index fc1759c03..4efd03b2d 100644 --- a/nac3core/src/toplevel/type_annotation.rs +++ b/nac3core/src/toplevel/type_annotation.rs @@ -12,6 +12,8 @@ pub enum TypeAnnotation { // can only be CustomClassKind VirtualKind(Box), TypeVarKind(Type), + ListKind(Box), + TupleKind(Vec), } pub fn parse_ast_to_type_annotation_kinds( @@ -55,7 +57,7 @@ pub fn parse_ast_to_type_annotation_kinds( } }, - // 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( 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::, _>>()?; + 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::, _>>()?; + Ok(unifier.add_ty(TypeEnum::TTuple { ty: tys })) + } } }