forked from M-Labs/nac3
1
0
Fork 0

nac3core: top level class method self parameter fixed

This commit is contained in:
ychenfo 2021-09-10 16:14:08 +08:00
parent 917d447605
commit 9eef51f29f
2 changed files with 53 additions and 48 deletions

View File

@ -642,7 +642,6 @@ impl TopLevelComposer {
let have_unique_fuction_parameter_name = args.args.iter().all(|x| { let have_unique_fuction_parameter_name = args.args.iter().all(|x| {
defined_paramter_name.insert(x.node.arg.clone()) defined_paramter_name.insert(x.node.arg.clone())
&& !keyword_list.contains(&x.node.arg) && !keyword_list.contains(&x.node.arg)
&& "self" != x.node.arg
}); });
if !have_unique_fuction_parameter_name { if !have_unique_fuction_parameter_name {
return Err("top level function must have unique parameter names \ return Err("top level function must have unique parameter names \
@ -837,57 +836,63 @@ impl TopLevelComposer {
let mut defined_paramter_name: HashSet<String> = HashSet::new(); let mut defined_paramter_name: HashSet<String> = HashSet::new();
let have_unique_fuction_parameter_name = args.args.iter().all(|x| { let have_unique_fuction_parameter_name = args.args.iter().all(|x| {
defined_paramter_name.insert(x.node.arg.clone()) defined_paramter_name.insert(x.node.arg.clone())
&& !keyword_list.contains(&x.node.arg) && (!keyword_list.contains(&x.node.arg) || x.node.arg == "self")
}); });
if !have_unique_fuction_parameter_name { if !have_unique_fuction_parameter_name {
return Err("class method must have unique parameter names \ return Err("class method must have unique parameter names \
and names thould not be the same as the keywords" and names thould not be the same as the keywords"
.into()); .into());
} }
if name == "__init__" && !defined_paramter_name.contains("self") {
return Err("__init__ function must have a `self` parameter".into());
}
let mut result = Vec::new(); let mut result = Vec::new();
for x in &args.args { for x in &args.args {
let name = x.node.arg.clone(); let name = x.node.arg.clone();
let type_ann = { if name != "self" {
let annotation_expr = x let type_ann = {
.node let annotation_expr = x
.annotation .node
.as_ref() .annotation
.ok_or_else(|| "type annotation needed".to_string())? .as_ref()
.as_ref(); .ok_or_else(|| "type annotation needed".to_string())?
parse_ast_to_type_annotation_kinds( .as_ref();
class_resolver.as_ref(), parse_ast_to_type_annotation_kinds(
temp_def_list, class_resolver.as_ref(),
unifier, temp_def_list,
primitives, unifier,
annotation_expr, primitives,
)? annotation_expr,
}; )?
// find type vars within this method parameter type annotation };
let type_vars_within = get_type_var_contained_in_type_annotation(&type_ann); // find type vars within this method parameter type annotation
// handle the class type var and the method type var let type_vars_within =
for type_var_within in type_vars_within { get_type_var_contained_in_type_annotation(&type_ann);
if let TypeAnnotation::TypeVarKind(ty) = type_var_within { // handle the class type var and the method type var
let id = Self::get_var_id(ty, unifier)?; for type_var_within in type_vars_within {
if let Some(prev_ty) = method_var_map.insert(id, ty) { if let TypeAnnotation::TypeVarKind(ty) = type_var_within {
// if already in the list, make sure they are the same? let id = Self::get_var_id(ty, unifier)?;
assert_eq!(prev_ty, ty); 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");
} }
} else {
unreachable!("must be type var annotation");
} }
// finish handling type vars
let dummy_func_arg = FuncArg {
name,
ty: unifier.get_fresh_var().0,
// TODO: symbol default value?
default_value: None,
};
// push the dummy type and the type annotation
// into the list for later unification
type_var_to_concrete_def.insert(dummy_func_arg.ty, type_ann.clone());
result.push(dummy_func_arg)
} }
// finish handling type vars
let dummy_func_arg = FuncArg {
name,
ty: unifier.get_fresh_var().0,
// TODO: symbol default value?
default_value: None,
};
// push the dummy type and the type annotation
// into the list for later unification
type_var_to_concrete_def.insert(dummy_func_arg.ty, type_ann.clone());
result.push(dummy_func_arg)
} }
result result
}; };

View File

@ -156,7 +156,7 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
vec![ vec![
indoc! {" indoc! {"
class A(): class A():
def __init__(): def __init__(self):
self.a: int32 = 3 self.a: int32 = 3
def fun(b: B): def fun(b: B):
pass pass
@ -165,12 +165,12 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
"}, "},
indoc! {" indoc! {"
class B(C): class B(C):
def __init__(): def __init__(self):
pass pass
"}, "},
indoc! {" indoc! {"
class C(A): class C(A):
def __init__(): def __init__(self):
pass pass
def fun(b: B): def fun(b: B):
a = 1 a = 1
@ -273,16 +273,16 @@ 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):
def __init__(): def __init__(self):
self.a: int64 = 123123123123 self.a: int64 = 123123123123
def fun(a: int32) -> V: def fun(self, a: int32) -> V:
pass pass
"}, "},
indoc! {" indoc! {"
class B: class B:
def __init__(): def __init__(self):
self.aa: bool = False self.aa: bool = False
def foo(b: T): def foo(self, b: T):
pass pass
"} "}
], ],
@ -343,7 +343,7 @@ 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]):
def __init__(v: V): def __init__(self, v: V):
self.a: T = 1 self.a: T = 1
self.b: V = v self.b: V = v
def fun(a: T) -> V: def fun(a: T) -> V:
@ -355,7 +355,7 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
"}, "},
indoc! {" indoc! {"
class B: class B:
def __init__(): def __init__(self):
pass pass
"} "}
], ],