forked from M-Labs/nac3
nac3core: top level class method self parameter fixed
This commit is contained in:
parent
917d447605
commit
9eef51f29f
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
"}
|
"}
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in New Issue