forked from M-Labs/nac3
nac3core: toplevel cleanup and add list and tuple support
This commit is contained in:
parent
40e58d02ed
commit
82c2edcf8d
|
@ -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");
|
||||||
|
|
|
@ -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 }))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue