hm-inference #6
|
@ -119,8 +119,8 @@ impl TopLevelComposer {
|
||||||
(primitives, unifier)
|
(primitives, unifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
pub fn new() -> (Vec<(String, DefinitionId, Type)>, Self) {
|
pub fn new() -> (Vec<(String, DefinitionId, Type)>, Self) {
|
||||||
let primitives = Self::make_primitives();
|
let primitives = Self::make_primitives();
|
||||||
// the def list including the entries of primitive info
|
// the def list including the entries of primitive info
|
||||||
|
@ -199,11 +199,11 @@ impl TopLevelComposer {
|
||||||
&mut self,
|
&mut self,
|
||||||
ast: ast::Stmt<()>,
|
ast: ast::Stmt<()>,
|
||||||
resolver: Option<Arc<Mutex<dyn SymbolResolver + Send>>>,
|
resolver: Option<Arc<Mutex<dyn SymbolResolver + Send>>>,
|
||||||
) -> Result<Vec<(String, DefinitionId, Type)>, String> {
|
) -> Result<(String, DefinitionId, Type), String> {
|
||||||
match &ast.node {
|
match &ast.node {
|
||||||
ast::StmtKind::ClassDef { name, body, .. } => {
|
ast::StmtKind::ClassDef { name, body, .. } => {
|
||||||
let class_name = name.to_string();
|
let class_name = name.to_string();
|
||||||
let def_list = self.definition_list.write();
|
let mut def_list = self.definition_list.write();
|
||||||
let class_def_id = def_list.len();
|
let class_def_id = def_list.len();
|
||||||
|
|
||||||
// add the class to the unifier
|
// add the class to the unifier
|
||||||
|
@ -212,19 +212,16 @@ impl TopLevelComposer {
|
||||||
fields: Default::default(),
|
fields: Default::default(),
|
||||||
params: Default::default(),
|
params: Default::default(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut ret_vector: Vec<(String, DefinitionId, Type)> =
|
|
||||||
vec![(class_name.clone(), DefinitionId(class_def_id), ty)];
|
|
||||||
// parse class def body and register class methods into the def list
|
// parse class def body and register class methods into the def list
|
||||||
// NOTE: module's symbol resolver would not know the name of the class methods,
|
// module's symbol resolver would not know the name of the class methods,
|
||||||
// thus cannot return their definition_id? so we have to manage it ourselves?
|
// thus cannot return their definition_id? so we have to manage it ourselves
|
||||||
// or do we return the class method list of (method_name, def_id, type) to
|
// by using the field `class_method_to_def_id`
|
||||||
// application to be used to build symbol resolver? <- current implementation
|
|
||||||
// FIXME: better do not return and let symbol resolver to manage the mangled name
|
|
||||||
for b in body {
|
for b in body {
|
||||||
if let ast::StmtKind::FunctionDef { name, .. } = &b.node {
|
if let ast::StmtKind::FunctionDef { name, .. } = &b.node {
|
||||||
let fun_name = name_mangling(class_name.clone(), name);
|
let fun_name = name_mangling(class_name.clone(), name);
|
||||||
let def_id = self.definition_list.len();
|
let def_id = def_list.len();
|
||||||
|
|
||||||
// add to unifier
|
// add to unifier
|
||||||
let ty = self.unifier.add_ty(TypeEnum::TFunc(
|
let ty = self.unifier.add_ty(TypeEnum::TFunc(
|
||||||
crate::typecheck::typedef::FunSignature {
|
crate::typecheck::typedef::FunSignature {
|
||||||
|
@ -233,51 +230,61 @@ impl TopLevelComposer {
|
||||||
vars: Default::default(),
|
vars: Default::default(),
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
// add to the definition list
|
// add to the definition list
|
||||||
self.definition_list.push(TopLevelDefInfo {
|
def_list.push(TopLevelDefInfo {
|
||||||
def: Self::make_top_level_function_def(fun_name.clone(), ty, None), // FIXME:
|
def: Self::make_top_level_function_def(fun_name.clone(), ty, resolver.clone()),
|
||||||
ty,
|
ty,
|
||||||
ast: None, // since it is inside the class def body statments
|
// since it is inside the class def body statments, the ast is None
|
||||||
|
ast: None,
|
||||||
});
|
});
|
||||||
ret_vector.push((fun_name, DefinitionId(def_id), ty));
|
|
||||||
|
// class method, do not let the symbol manager manage it, use our own map
|
||||||
|
// FIXME: maybe not do name magling, use map to map instead
|
||||||
|
self.class_method_to_def_id.insert(
|
||||||
|
fun_name,
|
||||||
|
DefinitionId(def_id)
|
||||||
|
);
|
||||||
|
|
||||||
// if it is the contructor, special handling is needed. In the above
|
// if it is the contructor, special handling is needed. In the above
|
||||||
// handling, we still add __init__ function to the class method
|
// handling, we still add __init__ function to the class method
|
||||||
if name == "__init__" {
|
if name == "__init__" {
|
||||||
self.definition_list.push(TopLevelDefInfo {
|
def_list.push(TopLevelDefInfo {
|
||||||
def: TopLevelDef::Initializer {
|
def: TopLevelDef::Initializer {
|
||||||
class_id: DefinitionId(class_def_id),
|
class_id: DefinitionId(class_def_id),
|
||||||
},
|
},
|
||||||
ty: self.primitives.none, // arbitary picked one
|
// arbitary picked one for the constructor
|
||||||
ast: None, // it is inside the class def body statments
|
ty: self.primitives.none,
|
||||||
|
// it is inside the class def body statments, so None
|
||||||
|
ast: None,
|
||||||
})
|
})
|
||||||
// FIXME: should we return this to the symbol resolver?, should be yes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the class to the definition list
|
// add the class to the definition list
|
||||||
self.definition_list.push(TopLevelDefInfo {
|
def_list.push(TopLevelDefInfo {
|
||||||
def: Self::make_top_level_class_def(class_def_id, resolver),
|
def: Self::make_top_level_class_def(class_def_id, resolver),
|
||||||
ast: Some(ast),
|
ast: Some(ast),
|
||||||
ty,
|
ty,
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(ret_vector)
|
Ok((class_name, DefinitionId(class_def_id), ty))
|
||||||
}
|
},
|
||||||
|
|
||||||
ast::StmtKind::FunctionDef { name, .. } => {
|
ast::StmtKind::FunctionDef { name, .. } => {
|
||||||
let fun_name = name.to_string();
|
let fun_name = name.to_string();
|
||||||
let def_id = self.definition_list.len();
|
|
||||||
// add to the unifier
|
// add to the unifier
|
||||||
let ty =
|
let ty = self.unifier.add_ty(TypeEnum::TFunc(crate::typecheck::typedef::FunSignature {
|
||||||
self.unifier.add_ty(TypeEnum::TFunc(crate::typecheck::typedef::FunSignature {
|
args: Default::default(),
|
||||||
args: Default::default(),
|
ret: self.primitives.none,
|
||||||
ret: self.primitives.none,
|
vars: Default::default(),
|
||||||
vars: Default::default(),
|
}));
|
||||||
}));
|
|
||||||
// add to the definition list
|
// add to the definition list
|
||||||
self.definition_list.push(TopLevelDefInfo {
|
let mut def_list = self.definition_list.write();
|
||||||
|
def_list.push(TopLevelDefInfo {
|
||||||
def: Self::make_top_level_function_def(
|
def: Self::make_top_level_function_def(
|
||||||
name.into(),
|
name.into(),
|
||||||
self.primitives.none,
|
self.primitives.none,
|
||||||
|
@ -287,7 +294,7 @@ impl TopLevelComposer {
|
||||||
ty,
|
ty,
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(vec![(fun_name, DefinitionId(def_id), ty)])
|
Ok((fun_name, DefinitionId(def_list.len() - 1), ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => Err("only registrations of top level classes/functions are supprted".into()),
|
_ => Err("only registrations of top level classes/functions are supprted".into()),
|
||||||
|
@ -296,7 +303,8 @@ impl TopLevelComposer {
|
||||||
|
|
||||||
/// this should be called after all top level classes are registered, and will actually fill in those fields of the previous dummy one
|
/// this should be called after all top level classes are registered, and will actually fill in those fields of the previous dummy one
|
||||||
pub fn analyze_top_level(&mut self) -> Result<(), String> {
|
pub fn analyze_top_level(&mut self) -> Result<(), String> {
|
||||||
for mut d in &mut self.definition_list {
|
for d in self.definition_list.write().iter_mut() {
|
||||||
|
// only analyze those with ast, and class_method(ast in class def)
|
||||||
if let Some(ast) = &d.ast {
|
if let Some(ast) = &d.ast {
|
||||||
match &ast.node {
|
match &ast.node {
|
||||||
ast::StmtKind::ClassDef {
|
ast::StmtKind::ClassDef {
|
||||||
|
@ -310,23 +318,25 @@ impl TopLevelComposer {
|
||||||
fields,
|
fields,
|
||||||
methods,
|
methods,
|
||||||
type_vars,
|
type_vars,
|
||||||
// resolver,
|
resolver,
|
||||||
) = if let TopLevelDef::Class {
|
) = if let TopLevelDef::Class {
|
||||||
object_id,
|
object_id,
|
||||||
ancestors,
|
ancestors,
|
||||||
fields,
|
fields,
|
||||||
methods,
|
methods,
|
||||||
type_vars,
|
type_vars,
|
||||||
resolver
|
resolver: Some(resolver)
|
||||||
} = &mut d.def {
|
} = &mut d.def {
|
||||||
(object_id, ancestors, fields, methods, type_vars) // FIXME: this unwrap is not safe
|
(object_id, ancestors, fields, methods, type_vars, resolver.lock())
|
||||||
} else { unreachable!() };
|
} else { unreachable!() };
|
||||||
|
|
||||||
// try to get mutable reference of the entry in the unification table, get the `TypeEnum`
|
// try to get mutable reference of the entry in the unification table, get the `TypeEnum`
|
||||||
let (params,
|
let (params,
|
||||||
fields
|
fields
|
||||||
) = if let TypeEnum::TObj {
|
) = if let TypeEnum::TObj {
|
||||||
params, // FIXME: this params is immutable, even if this is mutable, what should the key be, get the original typevar's var_id?
|
// FIXME: this params is immutable, even if this is mutable, what
|
||||||
|
// should the key be, get the original typevar's var_id?
|
||||||
|
params,
|
||||||
fields,
|
fields,
|
||||||
..
|
..
|
||||||
} = self.unifier.get_ty(d.ty).borrow() {
|
} = self.unifier.get_ty(d.ty).borrow() {
|
||||||
|
@ -337,7 +347,9 @@ impl TopLevelComposer {
|
||||||
// into the `bases` ast node
|
// into the `bases` ast node
|
||||||
for b in bases {
|
for b in bases {
|
||||||
match &b.node {
|
match &b.node {
|
||||||
// typevars bounded to the class, things like `class A(Generic[T, V, ImportedModule.T])`
|
// typevars bounded to the class, only support things like `class A(Generic[T, V])`,
|
||||||
|
// things like `class A(Generic[T, V, ImportedModule.T])` is not supported
|
||||||
|
// i.e. only simple names are allowed in the subscript
|
||||||
// should update the TopLevelDef::Class.typevars and the TypeEnum::TObj.params
|
// should update the TopLevelDef::Class.typevars and the TypeEnum::TObj.params
|
||||||
ast::ExprKind::Subscript {value, slice, ..} if {
|
ast::ExprKind::Subscript {value, slice, ..} if {
|
||||||
if let ast::ExprKind::Name {id, ..} = &value.node {
|
if let ast::ExprKind::Name {id, ..} = &value.node {
|
||||||
|
@ -345,22 +357,10 @@ impl TopLevelComposer {
|
||||||
} else { false }
|
} else { false }
|
||||||
} => {
|
} => {
|
||||||
match &slice.node {
|
match &slice.node {
|
||||||
// `class Foo(Generic[T, V, P, ImportedModule.T]):`
|
// `class Foo(Generic[T, V, P]):`
|
||||||
ast::ExprKind::Tuple {elts, ..} => {
|
ast::ExprKind::Tuple {elts, ..} => {
|
||||||
for e in elts {
|
for e in elts {
|
||||||
// TODO: I'd better parse the node to get the Type of the type vars(can have things like: A.B.C.typevar?)
|
// resolver.parse_type_annotation(self.definition_list.) // FIXME:
|
||||||
match &e.node {
|
|
||||||
ast::ExprKind::Name {id, ..} => {
|
|
||||||
// the def_list
|
|
||||||
// type_vars.push(resolver.get_symbol_type(id).ok_or_else(|| "unknown type variable".to_string())?); FIXME:
|
|
||||||
|
|
||||||
// the TypeEnum of the class
|
|
||||||
// FIXME: the `params` destructed above is not mutable, even if this is mutable, what should the key be?
|
|
||||||
unimplemented!()
|
|
||||||
},
|
|
||||||
|
|
||||||
_ => unimplemented!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -374,17 +374,11 @@ impl TopLevelComposer {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
},
|
},
|
||||||
|
|
||||||
// `class Foo(Generic[ImportedModule.T])`
|
_ => return Err("not supported, only simple names are allowed in the subscript".into())
|
||||||
ast::ExprKind::Attribute {value, attr, ..} => {
|
|
||||||
// TODO:
|
|
||||||
unimplemented!()
|
|
||||||
},
|
|
||||||
|
|
||||||
_ => return Err("not supported".into()) // NOTE: it is really all the supported cases?
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
// base class, name directly available inside the
|
/* // base class, name directly available inside the
|
||||||
// module, can use this module's symbol resolver
|
// module, can use this module's symbol resolver
|
||||||
ast::ExprKind::Name {id, ..} => {
|
ast::ExprKind::Name {id, ..} => {
|
||||||
// let def_id = resolver.get_identifier_def(id); FIXME:
|
// let def_id = resolver.get_identifier_def(id); FIXME:
|
||||||
|
@ -407,7 +401,9 @@ impl TopLevelComposer {
|
||||||
// `class Foo(ImportedModule.A[int, bool])`, A is a class with associated type variables
|
// `class Foo(ImportedModule.A[int, bool])`, A is a class with associated type variables
|
||||||
ast::ExprKind::Subscript {value, slice, ..} => {
|
ast::ExprKind::Subscript {value, slice, ..} => {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
},
|
}, */
|
||||||
|
|
||||||
|
// base class is possible in other cases, we parse for thr base class
|
||||||
_ => return Err("not supported".into())
|
_ => return Err("not supported".into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -444,7 +440,9 @@ impl TopLevelComposer {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => return Err("only expect function and class definitions to be submitted here to be analyzed".into())
|
node => {
|
||||||
|
return Err("only expect function and class definitions to be submitted here to be analyzed".into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue