forked from M-Labs/nac3
nac3core: top level fix class fields as nac3 spec
This commit is contained in:
parent
c7cb02b0f3
commit
147298ff40
|
@ -136,6 +136,8 @@ impl TopLevelComposer {
|
||||||
"none".into(),
|
"none".into(),
|
||||||
"None".into(),
|
"None".into(),
|
||||||
"self".into(),
|
"self".into(),
|
||||||
|
"Kernel".into(),
|
||||||
|
"KernelImmutable".into()
|
||||||
]),
|
]),
|
||||||
defined_class_method_name: Default::default(),
|
defined_class_method_name: Default::default(),
|
||||||
defined_class_name: Default::default(),
|
defined_class_name: Default::default(),
|
||||||
|
@ -825,9 +827,10 @@ impl TopLevelComposer {
|
||||||
};
|
};
|
||||||
let class_resolver = class_resolver.as_ref().unwrap();
|
let class_resolver = class_resolver.as_ref().unwrap();
|
||||||
let class_resolver = class_resolver.as_ref();
|
let class_resolver = class_resolver.as_ref();
|
||||||
|
|
||||||
|
let mut defined_fields: HashSet<String> = HashSet::new();
|
||||||
for b in class_body_ast {
|
for b in class_body_ast {
|
||||||
if let ast::StmtKind::FunctionDef { args, returns, name, body, .. } = &b.node {
|
if let ast::StmtKind::FunctionDef { args, returns, name, .. } = &b.node {
|
||||||
let (method_dummy_ty, method_id) =
|
let (method_dummy_ty, method_id) =
|
||||||
Self::get_class_method_def_info(class_methods_def, name)?;
|
Self::get_class_method_def_info(class_methods_def, name)?;
|
||||||
|
|
||||||
|
@ -968,61 +971,54 @@ impl TopLevelComposer {
|
||||||
// NOTE: unify now since function type is not in type annotation define
|
// NOTE: unify now since function type is not in type annotation define
|
||||||
// which is fine since type within method_type will be subst later
|
// which is fine since type within method_type will be subst later
|
||||||
unifier.unify(method_dummy_ty, method_type)?;
|
unifier.unify(method_dummy_ty, method_type)?;
|
||||||
|
} else if let ast::StmtKind::AnnAssign { target, annotation, value: None, .. } = &b.node {
|
||||||
|
if let ast::ExprKind::Name { id: attr, .. } = &target.node {
|
||||||
|
if defined_fields.insert(attr.to_string()) {
|
||||||
|
let dummy_field_type = unifier.get_fresh_var().0;
|
||||||
|
class_fields_def.push((attr.to_string(), dummy_field_type));
|
||||||
|
|
||||||
// class fields
|
// handle Kernel[T], KernelImmutable[T]
|
||||||
if name == "__init__" {
|
let annotation = {
|
||||||
for b in body {
|
match &annotation.as_ref().node {
|
||||||
let mut defined_fields: HashSet<String> = HashSet::new();
|
ast::ExprKind::Subscript { value, slice, .. } if {
|
||||||
// TODO: check the type of value, field instantiation check?
|
matches!(&value.node, ast::ExprKind::Name { id, .. } if id == "Kernel" || id == "KernelImmutable")
|
||||||
if let ast::StmtKind::AnnAssign { annotation, target, value: _, .. } =
|
} => slice,
|
||||||
&b.node
|
_ => annotation
|
||||||
{
|
}
|
||||||
if let ast::ExprKind::Attribute { value, attr, .. } = &target.node {
|
};
|
||||||
if matches!(&value.node, ast::ExprKind::Name { id, .. } if id == "self")
|
|
||||||
{
|
|
||||||
if defined_fields.insert(attr.to_string()) {
|
|
||||||
let dummy_field_type = unifier.get_fresh_var().0;
|
|
||||||
class_fields_def.push((attr.to_string(), dummy_field_type));
|
|
||||||
|
|
||||||
let annotation = parse_ast_to_type_annotation_kinds(
|
let annotation = parse_ast_to_type_annotation_kinds(
|
||||||
class_resolver.as_ref(),
|
class_resolver.as_ref(),
|
||||||
&temp_def_list,
|
&temp_def_list,
|
||||||
unifier,
|
unifier,
|
||||||
primitives,
|
primitives,
|
||||||
annotation.as_ref(),
|
annotation.as_ref(),
|
||||||
vec![(class_id, class_type_vars_def.clone())].into_iter().collect(),
|
vec![(class_id, class_type_vars_def.clone())].into_iter().collect(),
|
||||||
)?;
|
)?;
|
||||||
|
// find type vars within this return type annotation
|
||||||
// find type vars within this return type annotation
|
let type_vars_within =
|
||||||
let type_vars_within =
|
get_type_var_contained_in_type_annotation(&annotation);
|
||||||
get_type_var_contained_in_type_annotation(&annotation);
|
// 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(t) = type_var_within
|
||||||
if let TypeAnnotation::TypeVarKind(t) = type_var_within
|
{
|
||||||
{
|
if !class_type_vars_def.contains(&t) {
|
||||||
if !class_type_vars_def.contains(&t) {
|
return Err("class fields can only use type \
|
||||||
return Err("class fields can only use type \
|
vars declared as class generic type vars"
|
||||||
vars declared as class generic type vars"
|
.into());
|
||||||
.into());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachable!("must be type var annotation");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: allow class have field which type refers to Self type?
|
|
||||||
type_var_to_concrete_def
|
|
||||||
.insert(dummy_field_type, annotation);
|
|
||||||
} else {
|
|
||||||
return Err("same class fields defined twice".into());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("must be type var annotation");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
type_var_to_concrete_def
|
||||||
|
.insert(dummy_field_type, annotation);
|
||||||
|
} else {
|
||||||
|
return Err("same class fields defined twice".into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
continue;
|
return Err("unsupported statement type in class definition body".into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -156,8 +156,9 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
|
||||||
vec![
|
vec![
|
||||||
indoc! {"
|
indoc! {"
|
||||||
class A():
|
class A():
|
||||||
|
a: int32
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.a: int32 = 3
|
self.a = 3
|
||||||
def fun(self, b: B):
|
def fun(self, b: B):
|
||||||
pass
|
pass
|
||||||
def foo(self, a: T, b: V):
|
def foo(self, a: T, b: V):
|
||||||
|
@ -273,15 +274,17 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
|
||||||
vec![
|
vec![
|
||||||
indoc! {"
|
indoc! {"
|
||||||
class Generic_A(Generic[V], B):
|
class Generic_A(Generic[V], B):
|
||||||
|
a: int64
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.a: int64 = 123123123123
|
self.a = 123123123123
|
||||||
def fun(self, a: int32) -> V:
|
def fun(self, a: int32) -> V:
|
||||||
pass
|
pass
|
||||||
"},
|
"},
|
||||||
indoc! {"
|
indoc! {"
|
||||||
class B:
|
class B:
|
||||||
|
aa: bool
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.aa: bool = False
|
self.aa = False
|
||||||
def foo(self, b: T):
|
def foo(self, b: T):
|
||||||
pass
|
pass
|
||||||
"}
|
"}
|
||||||
|
@ -343,9 +346,11 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
|
||||||
"},
|
"},
|
||||||
indoc! {"
|
indoc! {"
|
||||||
class A(Generic[T, V]):
|
class A(Generic[T, V]):
|
||||||
|
a: T
|
||||||
|
b: V
|
||||||
def __init__(self, v: V):
|
def __init__(self, v: V):
|
||||||
self.a: T = 1
|
self.a = 1
|
||||||
self.b: V = v
|
self.b = v
|
||||||
def fun(self, a: T) -> V:
|
def fun(self, a: T) -> V:
|
||||||
pass
|
pass
|
||||||
"},
|
"},
|
||||||
|
@ -418,9 +423,11 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
|
||||||
vec![
|
vec![
|
||||||
indoc! {"
|
indoc! {"
|
||||||
class A(Generic[T, V]):
|
class A(Generic[T, V]):
|
||||||
|
a: A[float, bool]
|
||||||
|
b: B
|
||||||
def __init__(self, a: A[float, bool], b: B):
|
def __init__(self, a: A[float, bool], b: B):
|
||||||
self.a: A[float, bool] = a
|
self.a = a
|
||||||
self.b: B = b
|
self.b = b
|
||||||
def fun(self, a: A[float, bool]) -> A[bool, int32]:
|
def fun(self, a: A[float, bool]) -> A[bool, int32]:
|
||||||
pass
|
pass
|
||||||
"},
|
"},
|
||||||
|
@ -578,7 +585,7 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
|
||||||
vec!["a class def can only have at most one base class declaration and one generic declaration"];
|
vec!["a class def can only have at most one base class declaration and one generic declaration"];
|
||||||
"err multiple inheritance"
|
"err multiple inheritance"
|
||||||
)]
|
)]
|
||||||
fn test_simple_class_analyze(source: Vec<&str>, res: Vec<&str>) {
|
fn test_analyze(source: Vec<&str>, res: Vec<&str>) {
|
||||||
let print = false;
|
let print = false;
|
||||||
let mut composer = TopLevelComposer::new();
|
let mut composer = TopLevelComposer::new();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue