forked from M-Labs/nac3
handle class method/fields type var
This commit is contained in:
parent
018d6643e1
commit
b9a580d271
|
@ -1,4 +1,9 @@
|
||||||
use std::{collections::{HashMap, HashSet}, sync::Arc, ops::{Deref, DerefMut}, borrow::BorrowMut};
|
use std::{
|
||||||
|
borrow::BorrowMut,
|
||||||
|
collections::{HashMap, HashSet},
|
||||||
|
ops::{Deref, DerefMut},
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
use super::typecheck::type_inferencer::PrimitiveStore;
|
use super::typecheck::type_inferencer::PrimitiveStore;
|
||||||
use super::typecheck::typedef::{FunSignature, FuncArg, SharedUnifier, Type, TypeEnum, Unifier};
|
use super::typecheck::typedef::{FunSignature, FuncArg, SharedUnifier, Type, TypeEnum, Unifier};
|
||||||
|
@ -29,10 +34,10 @@ pub enum TopLevelDef {
|
||||||
name: String,
|
name: String,
|
||||||
// object ID used for TypeEnum
|
// object ID used for TypeEnum
|
||||||
object_id: DefinitionId,
|
object_id: DefinitionId,
|
||||||
// type variables bounded to the class.
|
/// type variables bounded to the class.
|
||||||
// the first field in the tuple is the var_id of the
|
/// the first field in the tuple is the var_id of the
|
||||||
// original typevar defined in the top level and returned
|
///original typevar defined in the top level and returned
|
||||||
// by the symbol resolver
|
/// by the symbol resolver
|
||||||
type_vars: Vec<(u32, Type)>,
|
type_vars: Vec<(u32, Type)>,
|
||||||
// class fields
|
// class fields
|
||||||
fields: Vec<(String, Type)>,
|
fields: Vec<(String, Type)>,
|
||||||
|
@ -467,7 +472,9 @@ impl TopLevelComposer {
|
||||||
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, class_id, class_type_vars) = {
|
||||||
if let TopLevelDef::Class { ancestors, resolver, object_id, type_vars, .. } = class_def.deref_mut() {
|
if let TopLevelDef::Class { ancestors, resolver, object_id, type_vars, .. } =
|
||||||
|
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
|
||||||
|
@ -522,14 +529,18 @@ impl TopLevelComposer {
|
||||||
|
|
||||||
// find the intersection between type vars occured in the base class type parameter
|
// find the intersection between type vars occured in the base class type parameter
|
||||||
// and the type vars occured in the class generic declaration
|
// and the type vars occured in the class generic declaration
|
||||||
let type_var_occured_in_base = get_type_var_contained_in_type_annotation(&base_ty);
|
let type_var_occured_in_base =
|
||||||
|
get_type_var_contained_in_type_annotation(&base_ty);
|
||||||
for type_ann in type_var_occured_in_base {
|
for type_ann in type_var_occured_in_base {
|
||||||
if let TypeAnnotation::TypeVarKind(id, ty) = type_ann {
|
if let TypeAnnotation::TypeVarKind(id, ty) = type_ann {
|
||||||
for (ty_id, class_typvar_ty) in class_type_vars.iter() {
|
for (ty_id, class_typvar_ty) in class_type_vars.iter() {
|
||||||
// if they refer to the same top level defined type var, we unify them together
|
// if they refer to the same top level defined type var, we unify them together
|
||||||
if id == *ty_id {
|
if id == *ty_id {
|
||||||
// assert to make sure
|
// assert to make sure
|
||||||
assert!(matches!(self.unifier.get_ty(ty).as_ref(), TypeEnum::TVar{ .. }));
|
assert!(matches!(
|
||||||
|
self.unifier.get_ty(ty).as_ref(),
|
||||||
|
TypeEnum::TVar { .. }
|
||||||
|
));
|
||||||
self.unifier.unify(ty, *class_typvar_ty)?;
|
self.unifier.unify(ty, *class_typvar_ty)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -540,16 +551,16 @@ impl TopLevelComposer {
|
||||||
|
|
||||||
class_ancestors.push(base_ty);
|
class_ancestors.push(base_ty);
|
||||||
} else {
|
} else {
|
||||||
return Err(
|
return Err("class base declaration can only be custom class".into());
|
||||||
"class base declaration can only be custom class".into()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// push self to the ancestors
|
// push self to the ancestors
|
||||||
class_ancestors.push(
|
class_ancestors.push(make_self_type_annotation(
|
||||||
make_self_type_annotation(&temp_def_list, class_id, self.unifier.borrow_mut())?
|
&temp_def_list,
|
||||||
)
|
class_id,
|
||||||
|
self.unifier.borrow_mut(),
|
||||||
|
)?)
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -636,19 +647,12 @@ impl TopLevelComposer {
|
||||||
})?
|
})?
|
||||||
.as_ref();
|
.as_ref();
|
||||||
|
|
||||||
|
|
||||||
let type_annotation = parse_ast_to_type_annotation_kinds(
|
let type_annotation = parse_ast_to_type_annotation_kinds(
|
||||||
resolver,
|
resolver,
|
||||||
temp_def_list.as_slice(),
|
temp_def_list.as_slice(),
|
||||||
unifier,
|
unifier,
|
||||||
primitives_store,
|
primitives_store,
|
||||||
annotation
|
annotation,
|
||||||
)?;
|
|
||||||
let ty = get_type_from_type_annotation_kinds(
|
|
||||||
temp_def_list.as_ref(),
|
|
||||||
unifier,
|
|
||||||
primitives_store,
|
|
||||||
&type_annotation
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// if there are same type variables appears, we only need to copy them once
|
// if there are same type variables appears, we only need to copy them once
|
||||||
|
@ -658,7 +662,10 @@ impl TopLevelComposer {
|
||||||
.map(|x| {
|
.map(|x| {
|
||||||
if let TypeAnnotation::TypeVarKind(id, ty) = x {
|
if let TypeAnnotation::TypeVarKind(id, ty) = x {
|
||||||
// assert here to make sure the ty is TypeEnum::TVar
|
// assert here to make sure the ty is TypeEnum::TVar
|
||||||
assert!(matches!(unifier.get_ty(ty).as_ref(), TypeEnum::TVar{ .. }));
|
assert!(matches!(
|
||||||
|
unifier.get_ty(ty).as_ref(),
|
||||||
|
TypeEnum::TVar { .. }
|
||||||
|
));
|
||||||
(id, ty)
|
(id, ty)
|
||||||
} else {
|
} else {
|
||||||
unreachable!("must be type var annotation kind")
|
unreachable!("must be type var annotation kind")
|
||||||
|
@ -666,7 +673,9 @@ impl TopLevelComposer {
|
||||||
})
|
})
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
for (top_level_var_id, ty) in type_vars_within {
|
for (top_level_var_id, ty) in type_vars_within {
|
||||||
if let Some(occured_ty) = occured_type_var.get(&top_level_var_id) {
|
if let Some(occured_ty) =
|
||||||
|
occured_type_var.get(&top_level_var_id)
|
||||||
|
{
|
||||||
// if already occured, we unify this two duplicated
|
// if already occured, we unify this two duplicated
|
||||||
// type var of the same top level type var
|
// type var of the same top level type var
|
||||||
unifier.unify(ty, *occured_ty)?;
|
unifier.unify(ty, *occured_ty)?;
|
||||||
|
@ -676,7 +685,9 @@ impl TopLevelComposer {
|
||||||
// we do not need to duplicate it again
|
// we do not need to duplicate it again
|
||||||
occured_type_var.insert(top_level_var_id, ty);
|
occured_type_var.insert(top_level_var_id, ty);
|
||||||
// the type var map to it self
|
// the type var map to it self
|
||||||
if let TypeEnum::TVar { id: self_id, .. } = unifier.get_ty(ty).as_ref() {
|
if let TypeEnum::TVar { id: self_id, .. } =
|
||||||
|
unifier.get_ty(ty).as_ref()
|
||||||
|
{
|
||||||
function_var_map.insert(*self_id, ty);
|
function_var_map.insert(*self_id, ty);
|
||||||
} else {
|
} else {
|
||||||
unreachable!("must be type var");
|
unreachable!("must be type var");
|
||||||
|
@ -684,6 +695,14 @@ impl TopLevelComposer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: get the actual ty after handling the type vars, really? why?
|
||||||
|
let ty = get_type_from_type_annotation_kinds(
|
||||||
|
temp_def_list.as_ref(),
|
||||||
|
unifier,
|
||||||
|
primitives_store,
|
||||||
|
&type_annotation,
|
||||||
|
)?;
|
||||||
|
|
||||||
// TODO: default value?
|
// TODO: default value?
|
||||||
Ok(FuncArg {
|
Ok(FuncArg {
|
||||||
name: x.node.arg.clone(),
|
name: x.node.arg.clone(),
|
||||||
|
@ -699,26 +718,25 @@ impl TopLevelComposer {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or_else(|| "function return type needed".to_string())?
|
.ok_or_else(|| "function return type needed".to_string())?
|
||||||
.as_ref();
|
.as_ref();
|
||||||
parse_ast_to_type_annotation_kinds(resolver, &temp_def_list, unifier, primitives_store, return_annotation)?
|
parse_ast_to_type_annotation_kinds(
|
||||||
};
|
resolver,
|
||||||
let return_ty =
|
|
||||||
get_type_from_type_annotation_kinds(
|
|
||||||
&temp_def_list,
|
&temp_def_list,
|
||||||
unifier,
|
unifier,
|
||||||
primitives_store,
|
primitives_store,
|
||||||
&return_ty_annotation
|
return_annotation,
|
||||||
)?;
|
)?
|
||||||
|
};
|
||||||
|
|
||||||
let type_vars_within =
|
let type_vars_within =
|
||||||
get_type_var_contained_in_type_annotation(&return_ty_annotation)
|
get_type_var_contained_in_type_annotation(&return_ty_annotation)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|x|
|
.map(|x| {
|
||||||
if let TypeAnnotation::TypeVarKind(id, ty) = x {
|
if let TypeAnnotation::TypeVarKind(id, ty) = x {
|
||||||
(id, ty)
|
(id, ty)
|
||||||
} else {
|
} else {
|
||||||
unreachable!("must be type var here")
|
unreachable!("must be type var here")
|
||||||
}
|
}
|
||||||
)
|
})
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
for (top_level_var_id, ty) in type_vars_within {
|
for (top_level_var_id, ty) in type_vars_within {
|
||||||
if let Some(existing_ty) = occured_type_var.get(&top_level_var_id) {
|
if let Some(existing_ty) = occured_type_var.get(&top_level_var_id) {
|
||||||
|
@ -729,6 +747,14 @@ impl TopLevelComposer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: get the actual ty after handling the type vars, really? why?
|
||||||
|
let return_ty = get_type_from_type_annotation_kinds(
|
||||||
|
&temp_def_list,
|
||||||
|
unifier,
|
||||||
|
primitives_store,
|
||||||
|
&return_ty_annotation,
|
||||||
|
)?;
|
||||||
|
|
||||||
let function_ty = unifier.add_ty(TypeEnum::TFunc(
|
let function_ty = unifier.add_ty(TypeEnum::TFunc(
|
||||||
FunSignature { args: arg_types, ret: return_ty, vars: function_var_map }
|
FunSignature { args: arg_types, ret: return_ty, vars: function_var_map }
|
||||||
.into(),
|
.into(),
|
||||||
|
@ -807,8 +833,24 @@ impl TopLevelComposer {
|
||||||
|
|
||||||
// handle var map, to create a new copy of type var
|
// handle var map, to create a new copy of type var
|
||||||
// while tracking the type var associated with class
|
// while tracking the type var associated with class
|
||||||
// TODO: type vars occured as applications of generic classes is not handled
|
// from the duplicated type var's var_id to themselves
|
||||||
let mut method_var_map: HashMap<u32, Type> = HashMap::new();
|
// include the class type vars like the type var context of the method
|
||||||
|
let mut method_var_map: HashMap<u32, Type> = class_type_vars_def
|
||||||
|
.iter()
|
||||||
|
.map(|(_, ty)| {
|
||||||
|
if let TypeEnum::TVar { id, .. } = unifier.get_ty(*ty).as_ref() {
|
||||||
|
(*id, *ty)
|
||||||
|
} else {
|
||||||
|
unreachable!("must be type var here")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// from the def_id of top level type vars to duplicated type vars
|
||||||
|
// also include the class type var like the type var context of the method
|
||||||
|
let mut occured_type_vars: HashMap<u32, Type> =
|
||||||
|
class_type_vars_def.iter().map(|(id, ty)| (*id, *ty)).collect();
|
||||||
|
|
||||||
let arg_types: Vec<FuncArg> = {
|
let arg_types: Vec<FuncArg> = {
|
||||||
// check method parameters cannot have same name
|
// check method parameters cannot have same name
|
||||||
let mut defined_paramter_name: HashSet<String> = HashSet::new();
|
let mut defined_paramter_name: HashSet<String> = HashSet::new();
|
||||||
|
@ -837,57 +879,39 @@ impl TopLevelComposer {
|
||||||
annotation_expr,
|
annotation_expr,
|
||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
// handle to differentiate type vars that are
|
|
||||||
// asscosiated with the class and that are not
|
|
||||||
|
|
||||||
let type_vars_within = get_type_var_contained_in_type_annotation(&type_ann);
|
// find type vars within this method parameter type annotation
|
||||||
|
let type_vars_within =
|
||||||
|
get_type_var_contained_in_type_annotation(&type_ann);
|
||||||
|
// 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(top_level_id, ty) = type_var_within {
|
if let TypeAnnotation::TypeVarKind(top_level_id, ty) =
|
||||||
for (class_type_var_top_level_id, class_type_var_ty) in class_type_vars_def.iter() {
|
type_var_within
|
||||||
if top_level_id == *class_type_var_top_level_id {
|
{
|
||||||
unifier.unify(ty, *class_type_var_ty)?;
|
if let Some(duped_ty) = occured_type_vars.get(&top_level_id) {
|
||||||
|
// if already occured, not matter if it is class typevar or method typevar, just unify
|
||||||
|
unifier.unify(ty, *duped_ty)?;
|
||||||
|
} else {
|
||||||
|
// if not insert them to the occured_type_vars and the method_varmap
|
||||||
|
// note that the content to insert is different
|
||||||
|
occured_type_vars.insert(top_level_id, ty);
|
||||||
|
method_var_map.insert(
|
||||||
|
if let TypeEnum::TVar { id, .. } =
|
||||||
|
unifier.get_ty(ty).as_ref()
|
||||||
|
{
|
||||||
|
*id
|
||||||
|
} else {
|
||||||
|
unreachable!("must be type var")
|
||||||
|
},
|
||||||
|
ty,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// note that this has to be done after the unify step between the common type vars
|
|
||||||
// between the method and the class(unify of type variables associated with class)
|
|
||||||
// since after unification, the var_id will change.
|
|
||||||
method_var_map.insert()
|
|
||||||
} else {
|
} else {
|
||||||
unreachable!("must be type var annotation");
|
unreachable!("must be type var annotation");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if let TypeAnnotation::TypeVarKind(id, ty) = &type_ann {
|
|
||||||
// let associated = class_type_vars_def
|
|
||||||
// .iter()
|
|
||||||
// .filter(|(class_type_var_id, _)| *class_type_var_id == *id)
|
|
||||||
// .collect_vec();
|
|
||||||
// match associated.len() {
|
|
||||||
// // 0, do nothing, this is not a type var
|
|
||||||
// // associated with the method's class
|
|
||||||
// // TODO: but this type var can occur multiple times in this
|
|
||||||
// // method's param list, still need to keep track of type vars
|
|
||||||
// // associated with this function
|
|
||||||
// 0 => {}
|
|
||||||
// // is type var associated with class, do the unification here
|
|
||||||
// 1 => {
|
|
||||||
// unifier.unify(*ty, associated[0].1)?;
|
|
||||||
// }
|
|
||||||
// _ => {
|
|
||||||
// unreachable!("there should not be duplicate type var");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // just insert the id and ty of self
|
|
||||||
// // since the function is not instantiated yet
|
|
||||||
// if let TypeEnum::TVar { id, .. } = unifier.get_ty(*ty).as_ref() {
|
|
||||||
// method_var_map.insert(*id, *ty);
|
|
||||||
// } else {
|
|
||||||
// unreachable!("must be type var")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
// finish handling type vars
|
||||||
let dummy_func_arg = FuncArg {
|
let dummy_func_arg = FuncArg {
|
||||||
name,
|
name,
|
||||||
ty: unifier.get_fresh_var().0,
|
ty: unifier.get_fresh_var().0,
|
||||||
|
@ -902,23 +926,22 @@ impl TopLevelComposer {
|
||||||
// if the parameter name is self
|
// if the parameter name is self
|
||||||
// python does not seem to enforce the name
|
// python does not seem to enforce the name
|
||||||
// representing the self class object to be
|
// representing the self class object to be
|
||||||
// `self`, but we do it here
|
// `self`??, but we do it here
|
||||||
|
|
||||||
let dummy_func_arg = FuncArg {
|
let dummy_func_arg = FuncArg {
|
||||||
name: "self".into(),
|
name: "self".into(),
|
||||||
ty: unifier.get_fresh_var().0,
|
ty: unifier.get_fresh_var().0,
|
||||||
default_value: None,
|
default_value: None,
|
||||||
};
|
};
|
||||||
type_var_to_concrete_def
|
type_var_to_concrete_def.insert(
|
||||||
.insert(
|
|
||||||
dummy_func_arg.ty,
|
dummy_func_arg.ty,
|
||||||
make_self_type_annotation(temp_def_list, *class_id, unifier)?
|
make_self_type_annotation(temp_def_list, *class_id, unifier)?,
|
||||||
);
|
);
|
||||||
result.push(dummy_func_arg);
|
result.push(dummy_func_arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
};
|
};
|
||||||
|
|
||||||
let ret_type = {
|
let ret_type = {
|
||||||
if name != "__init__" {
|
if name != "__init__" {
|
||||||
let result = returns
|
let result = returns
|
||||||
|
@ -932,16 +955,45 @@ impl TopLevelComposer {
|
||||||
primitives,
|
primitives,
|
||||||
result,
|
result,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
// find type vars within this return type annotation
|
||||||
|
let type_vars_within =
|
||||||
|
get_type_var_contained_in_type_annotation(&annotation);
|
||||||
|
// handle the class type var and the method type var
|
||||||
|
for type_var_within in type_vars_within {
|
||||||
|
if let TypeAnnotation::TypeVarKind(top_level_id, ty) = type_var_within {
|
||||||
|
if let Some(duped_ty) = occured_type_vars.get(&top_level_id) {
|
||||||
|
// if already occured, not matter if it is class typevar or method typevar, just unify
|
||||||
|
unifier.unify(ty, *duped_ty)?;
|
||||||
|
} else {
|
||||||
|
// if not insert them to the occured_type_vars and the method_varmap
|
||||||
|
// note that the content to insert is different
|
||||||
|
occured_type_vars.insert(top_level_id, ty);
|
||||||
|
method_var_map.insert(
|
||||||
|
if let TypeEnum::TVar { id, .. } =
|
||||||
|
unifier.get_ty(ty).as_ref()
|
||||||
|
{
|
||||||
|
*id
|
||||||
|
} else {
|
||||||
|
unreachable!("must be type var")
|
||||||
|
},
|
||||||
|
ty,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("must be type var annotation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let dummy_return_type = unifier.get_fresh_var().0;
|
let dummy_return_type = unifier.get_fresh_var().0;
|
||||||
type_var_to_concrete_def.insert(dummy_return_type, annotation.clone());
|
type_var_to_concrete_def.insert(dummy_return_type, annotation.clone());
|
||||||
dummy_return_type
|
dummy_return_type
|
||||||
} else {
|
} else {
|
||||||
// if is the "__init__" function, the return type is self
|
// if is the "__init__" function, the return type is self
|
||||||
let dummy_return_type = unifier.get_fresh_var().0;
|
let dummy_return_type = unifier.get_fresh_var().0;
|
||||||
type_var_to_concrete_def
|
type_var_to_concrete_def.insert(
|
||||||
.insert(
|
|
||||||
dummy_return_type,
|
dummy_return_type,
|
||||||
make_self_type_annotation(temp_def_list, *class_id, unifier)?
|
make_self_type_annotation(temp_def_list, *class_id, unifier)?,
|
||||||
);
|
);
|
||||||
dummy_return_type
|
dummy_return_type
|
||||||
}
|
}
|
||||||
|
@ -950,7 +1002,7 @@ impl TopLevelComposer {
|
||||||
let method_type = unifier.add_ty(TypeEnum::TFunc(
|
let method_type = unifier.add_ty(TypeEnum::TFunc(
|
||||||
FunSignature { args: arg_types, ret: ret_type, vars: method_var_map }.into(),
|
FunSignature { args: arg_types, ret: ret_type, vars: method_var_map }.into(),
|
||||||
));
|
));
|
||||||
// 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)?;
|
||||||
|
|
||||||
|
@ -968,6 +1020,7 @@ impl TopLevelComposer {
|
||||||
if defined_fields.insert(attr.to_string()) {
|
if defined_fields.insert(attr.to_string()) {
|
||||||
let dummy_field_type = unifier.get_fresh_var().0;
|
let dummy_field_type = unifier.get_fresh_var().0;
|
||||||
class_fields_def.push((attr.to_string(), dummy_field_type));
|
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,
|
class_resolver,
|
||||||
&temp_def_list,
|
&temp_def_list,
|
||||||
|
@ -975,6 +1028,28 @@ impl TopLevelComposer {
|
||||||
primitives,
|
primitives,
|
||||||
annotation.as_ref(),
|
annotation.as_ref(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
// find type vars within this return type annotation
|
||||||
|
let type_vars_within =
|
||||||
|
get_type_var_contained_in_type_annotation(&annotation);
|
||||||
|
// handle the class type var and the method type var
|
||||||
|
for type_var_within in type_vars_within {
|
||||||
|
if let TypeAnnotation::TypeVarKind(top_level_id, ty) =
|
||||||
|
type_var_within
|
||||||
|
{
|
||||||
|
if let Some(duped_ty) =
|
||||||
|
occured_type_vars.get(&top_level_id)
|
||||||
|
{
|
||||||
|
// if already occured, not matter if it is class typevar or method typevar, just unify
|
||||||
|
unifier.unify(ty, *duped_ty)?;
|
||||||
|
} else {
|
||||||
|
return Err("this type var is not available inside this function".into());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("must be type var annotation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type_var_to_concrete_def
|
type_var_to_concrete_def
|
||||||
.insert(dummy_field_type, annotation);
|
.insert(dummy_field_type, annotation);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1007,7 +1082,7 @@ impl TopLevelComposer {
|
||||||
/// get all base class def id of a class, including itself
|
/// get all base class def id of a class, including itself
|
||||||
fn get_all_base(
|
fn get_all_base(
|
||||||
child: DefinitionId,
|
child: DefinitionId,
|
||||||
temp_def_list: &[Arc<RwLock<TopLevelDef>>]
|
temp_def_list: &[Arc<RwLock<TopLevelDef>>],
|
||||||
) -> Vec<DefinitionId> {
|
) -> Vec<DefinitionId> {
|
||||||
let mut result: Vec<DefinitionId> = Vec::new();
|
let mut result: Vec<DefinitionId> = Vec::new();
|
||||||
let child_def = temp_def_list.get(child.0).unwrap();
|
let child_def = temp_def_list.get(child.0).unwrap();
|
||||||
|
@ -1031,31 +1106,4 @@ impl TopLevelComposer {
|
||||||
result.push(child);
|
result.push(child);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// handle the method function types (especially the type vars things)
|
|
||||||
/// arg: ast node Arguments, contains lists of various kinds of function parameters, now only deal with arg.arg
|
|
||||||
/// resolver: the resolver of the corresponding top_level_function/class
|
|
||||||
/// class_type_vars: if is class method, this is the reference to the field: TopLevelDef::Class.type_vars \
|
|
||||||
/// \
|
|
||||||
/// return a tuple of three:
|
|
||||||
/// 0. vector of FuncArg which is used to construct the FunSignature
|
|
||||||
/// 1. Hashmap of occured type vars for later analyze the return type
|
|
||||||
/// 2. Hashmap of the function type var map to build the FunSignature
|
|
||||||
fn analyze_function_args_type(
|
|
||||||
arg: &ast::Arguments,
|
|
||||||
resolver: &(dyn SymbolResolver + Send + Sync),
|
|
||||||
class_type_vars: Option<&[(u32, Type)]>
|
|
||||||
) -> (Vec<FuncArg>, HashMap<u32, Type>, HashMap<u32, Type>) {
|
|
||||||
let mut occured_type_var: HashMap<u32, Type> = HashMap::new();
|
|
||||||
let mut function_var_map: HashMap<u32, Type> = HashMap::new();
|
|
||||||
// the type var of the class is essentially the occured_type_def
|
|
||||||
if let Some(class_type_vars) = class_type_vars {
|
|
||||||
occured_type_var.extend(class_type_vars.into_iter());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,18 +42,17 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
|
||||||
if let TopLevelDef::Class { type_vars, .. } = &*def {
|
if let TopLevelDef::Class { type_vars, .. } = &*def {
|
||||||
// also check param number here
|
// also check param number here
|
||||||
if !type_vars.is_empty() {
|
if !type_vars.is_empty() {
|
||||||
return Err(format!("expect {} type variable parameter but got 0", type_vars.len()))
|
return Err(format!(
|
||||||
|
"expect {} type variable parameter but got 0",
|
||||||
|
type_vars.len()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
Ok(TypeAnnotation::CustomClassKind {
|
Ok(TypeAnnotation::CustomClassKind { id: obj_id, params: vec![] })
|
||||||
id: obj_id,
|
|
||||||
params: vec![],
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
Err("function cannot be used as a type".into())
|
Err("function cannot be used as a type".into())
|
||||||
}
|
}
|
||||||
} else if let Some(ty) = resolver.get_symbol_type(unifier, primitives, id) {
|
} else if let Some(ty) = resolver.get_symbol_type(unifier, primitives, id) {
|
||||||
if let TypeEnum::TVar { id, .. } = unifier.get_ty(ty).as_ref()
|
if let TypeEnum::TVar { id, .. } = unifier.get_ty(ty).as_ref() {
|
||||||
{
|
|
||||||
// NOTE: always create a new one here
|
// NOTE: always create a new one here
|
||||||
// and later unify if needed
|
// and later unify if needed
|
||||||
// but record the var_id of the original type var
|
// but record the var_id of the original type var
|
||||||
|
@ -61,7 +60,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
|
||||||
Ok(TypeAnnotation::TypeVarKind(
|
Ok(TypeAnnotation::TypeVarKind(
|
||||||
// this id is the id of the top level type var
|
// this id is the id of the top level type var
|
||||||
*id,
|
*id,
|
||||||
duplicate_type_var(unifier, ty).0
|
duplicate_type_var(unifier, ty).0,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
Err("not a type variable identifier".into())
|
Err("not a type variable identifier".into())
|
||||||
|
@ -125,13 +124,10 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
|
||||||
"expect {} type parameters but got {}",
|
"expect {} type parameters but got {}",
|
||||||
type_vars.len(),
|
type_vars.len(),
|
||||||
param_type_infos.len()
|
param_type_infos.len()
|
||||||
))
|
));
|
||||||
}
|
}
|
||||||
// NOTE: allow type var in class generic application list
|
// NOTE: allow type var in class generic application list
|
||||||
Ok(TypeAnnotation::CustomClassKind {
|
Ok(TypeAnnotation::CustomClassKind { id: obj_id, params: param_type_infos })
|
||||||
id: obj_id,
|
|
||||||
params: param_type_infos,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
Err("function cannot be used as a type".into())
|
Err("function cannot be used as a type".into())
|
||||||
}
|
}
|
||||||
|
@ -173,7 +169,7 @@ pub fn get_type_from_type_annotation_kinds(
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
// FIXME: TODO: cannot directy subst type var here? need to subst types in fields/methods
|
// NOTE: cannot directy subst type var here? need to subst types in fields/methods?
|
||||||
let subst = type_vars
|
let subst = type_vars
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| {
|
.map(|x| {
|
||||||
|
@ -227,10 +223,7 @@ pub fn get_type_from_type_annotation_kinds(
|
||||||
/// the second return is the var_id of the duplicated type \
|
/// the second return is the var_id of the duplicated type \
|
||||||
/// the third return is the var_id of the original type
|
/// the third return is the var_id of the original type
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn duplicate_type_var(
|
pub fn duplicate_type_var(unifier: &mut Unifier, type_var: Type) -> (Type, u32, u32) {
|
||||||
unifier: &mut Unifier,
|
|
||||||
type_var: Type
|
|
||||||
) -> (Type, u32, u32) {
|
|
||||||
let ty = unifier.get_ty(type_var);
|
let ty = unifier.get_ty(type_var);
|
||||||
if let TypeEnum::TVar { id, range, .. } = ty.as_ref() {
|
if let TypeEnum::TVar { id, range, .. } = ty.as_ref() {
|
||||||
let range = range.borrow();
|
let range = range.borrow();
|
||||||
|
@ -263,11 +256,10 @@ pub fn duplicate_type_var(
|
||||||
pub fn make_self_type_annotation(
|
pub fn make_self_type_annotation(
|
||||||
top_level_defs: &[Arc<RwLock<TopLevelDef>>],
|
top_level_defs: &[Arc<RwLock<TopLevelDef>>],
|
||||||
def_id: DefinitionId,
|
def_id: DefinitionId,
|
||||||
unifier: &mut Unifier,
|
_unifier: &mut Unifier,
|
||||||
) -> Result<TypeAnnotation, String> {
|
) -> Result<TypeAnnotation, String> {
|
||||||
let obj_def = top_level_defs
|
let obj_def =
|
||||||
.get(def_id.0)
|
top_level_defs.get(def_id.0).ok_or_else(|| "invalid definition id".to_string())?;
|
||||||
.ok_or_else(|| "invalid definition id".to_string())?;
|
|
||||||
let obj_def = obj_def.read();
|
let obj_def = obj_def.read();
|
||||||
let obj_def = obj_def.deref();
|
let obj_def = obj_def.deref();
|
||||||
|
|
||||||
|
@ -276,10 +268,10 @@ pub fn make_self_type_annotation(
|
||||||
id: def_id,
|
id: def_id,
|
||||||
params: type_vars
|
params: type_vars
|
||||||
.iter()
|
.iter()
|
||||||
// note here the var_id also points to the var_id of
|
// NOTE: here the var_id also points to the var_id of
|
||||||
// the top level defined type var's var id
|
// the top level defined type var's var id
|
||||||
.map(|(var_id, ty)| TypeAnnotation::TypeVarKind(*var_id, *ty))
|
.map(|(var_id, ty)| TypeAnnotation::TypeVarKind(*var_id, *ty))
|
||||||
.collect_vec()
|
.collect_vec(),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
unreachable!("must be top level class def here")
|
unreachable!("must be top level class def here")
|
||||||
|
@ -293,14 +285,14 @@ pub fn get_type_var_contained_in_type_annotation(ann: &TypeAnnotation) -> Vec<Ty
|
||||||
let mut result: Vec<TypeAnnotation> = Vec::new();
|
let mut result: Vec<TypeAnnotation> = Vec::new();
|
||||||
match ann {
|
match ann {
|
||||||
TypeAnnotation::TypeVarKind(..) => result.push(ann.clone()),
|
TypeAnnotation::TypeVarKind(..) => result.push(ann.clone()),
|
||||||
TypeAnnotation::VirtualKind(ann) => result.extend(
|
TypeAnnotation::VirtualKind(ann) => {
|
||||||
get_type_var_contained_in_type_annotation(ann.as_ref())
|
result.extend(get_type_var_contained_in_type_annotation(ann.as_ref()))
|
||||||
),
|
}
|
||||||
TypeAnnotation::CustomClassKind { params, .. } => {
|
TypeAnnotation::CustomClassKind { params, .. } => {
|
||||||
for p in params {
|
for p in params {
|
||||||
result.extend(get_type_var_contained_in_type_annotation(p));
|
result.extend(get_type_var_contained_in_type_annotation(p));
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
|
|
Loading…
Reference in New Issue