forked from M-Labs/nac3
formating
This commit is contained in:
parent
529442590f
commit
6279dbb589
@ -4,8 +4,8 @@ use std::{collections::HashMap, collections::HashSet, sync::Arc};
|
|||||||
|
|
||||||
use super::typecheck::type_inferencer::PrimitiveStore;
|
use super::typecheck::type_inferencer::PrimitiveStore;
|
||||||
use super::typecheck::typedef::{SharedUnifier, Type, TypeEnum, Unifier};
|
use super::typecheck::typedef::{SharedUnifier, Type, TypeEnum, Unifier};
|
||||||
use crate::{symbol_resolver::SymbolResolver, typecheck::typedef::Mapping};
|
|
||||||
use crate::typecheck::typedef::{FunSignature, FuncArg};
|
use crate::typecheck::typedef::{FunSignature, FuncArg};
|
||||||
|
use crate::{symbol_resolver::SymbolResolver, typecheck::typedef::Mapping};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use rustpython_parser::ast::{self, Stmt};
|
use rustpython_parser::ast::{self, Stmt};
|
||||||
@ -68,7 +68,6 @@ pub struct TopLevelContext {
|
|||||||
pub unifiers: Arc<RwLock<Vec<(SharedUnifier, PrimitiveStore)>>>,
|
pub unifiers: Arc<RwLock<Vec<(SharedUnifier, PrimitiveStore)>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct TopLevelComposer {
|
pub struct TopLevelComposer {
|
||||||
// list of top level definitions, same as top level context
|
// list of top level definitions, same as top level context
|
||||||
pub definition_ast_list: Arc<RwLock<Vec<(Arc<RwLock<TopLevelDef>>, Option<ast::Stmt<()>>)>>>,
|
pub definition_ast_list: Arc<RwLock<Vec<(Arc<RwLock<TopLevelDef>>, Option<ast::Stmt<()>>)>>>,
|
||||||
@ -84,12 +83,8 @@ pub struct TopLevelComposer {
|
|||||||
|
|
||||||
impl TopLevelComposer {
|
impl TopLevelComposer {
|
||||||
pub fn to_top_level_context(&self) -> TopLevelContext {
|
pub fn to_top_level_context(&self) -> TopLevelContext {
|
||||||
let def_list = self
|
let def_list =
|
||||||
.definition_ast_list
|
self.definition_ast_list.read().iter().map(|(x, _)| x.clone()).collect::<Vec<_>>();
|
||||||
.read()
|
|
||||||
.iter()
|
|
||||||
.map(|(x, _)| x.clone())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
TopLevelContext {
|
TopLevelContext {
|
||||||
definitions: RwLock::new(def_list).into(),
|
definitions: RwLock::new(def_list).into(),
|
||||||
// FIXME: all the big unifier or?
|
// FIXME: all the big unifier or?
|
||||||
@ -151,8 +146,9 @@ impl TopLevelComposer {
|
|||||||
|
|
||||||
let composer = TopLevelComposer {
|
let composer = TopLevelComposer {
|
||||||
definition_ast_list: RwLock::new(
|
definition_ast_list: RwLock::new(
|
||||||
top_level_def_list.into_iter().zip(ast_list).collect_vec()
|
top_level_def_list.into_iter().zip(ast_list).collect_vec(),
|
||||||
).into(),
|
)
|
||||||
|
.into(),
|
||||||
primitives: primitives.0,
|
primitives: primitives.0,
|
||||||
unifier: primitives.1,
|
unifier: primitives.1,
|
||||||
class_method_to_def_id: Default::default(),
|
class_method_to_def_id: Default::default(),
|
||||||
@ -217,16 +213,21 @@ impl TopLevelComposer {
|
|||||||
// since later when registering class method, ast will still be used,
|
// since later when registering class method, ast will still be used,
|
||||||
// here push None temporarly, later will move the ast inside
|
// here push None temporarly, later will move the ast inside
|
||||||
let mut class_def_ast = (
|
let mut class_def_ast = (
|
||||||
Arc::new(RwLock::new(
|
Arc::new(RwLock::new(Self::make_top_level_class_def(
|
||||||
Self::make_top_level_class_def(class_def_id, resolver.clone())
|
class_def_id,
|
||||||
)),
|
resolver.clone(),
|
||||||
None
|
))),
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
// parse class def body and register class methods into the def list.
|
// parse class def body and register class methods into the def list.
|
||||||
// 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
|
// thus cannot return their definition_id
|
||||||
let mut class_method_name_def_ids: Vec<(String, Arc<RwLock<TopLevelDef>>, DefinitionId)> = Vec::new();
|
let mut class_method_name_def_ids: Vec<(
|
||||||
|
String,
|
||||||
|
Arc<RwLock<TopLevelDef>>,
|
||||||
|
DefinitionId,
|
||||||
|
)> = Vec::new();
|
||||||
let mut class_method_index_offset = 0;
|
let mut class_method_index_offset = 0;
|
||||||
for b in body {
|
for b in body {
|
||||||
if let ast::StmtKind::FunctionDef { name: method_name, .. } = &b.node {
|
if let ast::StmtKind::FunctionDef { name: method_name, .. } = &b.node {
|
||||||
@ -244,8 +245,9 @@ impl TopLevelComposer {
|
|||||||
method_name.clone(),
|
method_name.clone(),
|
||||||
self.primitives.none,
|
self.primitives.none,
|
||||||
resolver.clone(),
|
resolver.clone(),
|
||||||
)).into(),
|
))
|
||||||
DefinitionId(method_def_id)
|
.into(),
|
||||||
|
DefinitionId(method_def_id),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -260,13 +262,11 @@ impl TopLevelComposer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// put the constructor into the def_list
|
// put the constructor into the def_list
|
||||||
def_list
|
def_list.push((
|
||||||
.push((
|
RwLock::new(TopLevelDef::Initializer { class_id: DefinitionId(class_def_id) })
|
||||||
RwLock::new(
|
.into(),
|
||||||
TopLevelDef::Initializer { class_id: DefinitionId(class_def_id) }
|
None,
|
||||||
).into(),
|
));
|
||||||
None
|
|
||||||
));
|
|
||||||
|
|
||||||
// class, put its def_id into the to be analyzed set
|
// class, put its def_id into the to be analyzed set
|
||||||
self.to_be_analyzed_class.push(DefinitionId(class_def_id));
|
self.to_be_analyzed_class.push(DefinitionId(class_def_id));
|
||||||
@ -279,9 +279,13 @@ impl TopLevelComposer {
|
|||||||
|
|
||||||
// add to the definition list
|
// add to the definition list
|
||||||
def_list.push((
|
def_list.push((
|
||||||
RwLock::new(Self::make_top_level_function_def(name.into(), self.primitives.none, resolver))
|
RwLock::new(Self::make_top_level_function_def(
|
||||||
.into(),
|
name.into(),
|
||||||
Some(ast)
|
self.primitives.none,
|
||||||
|
resolver,
|
||||||
|
))
|
||||||
|
.into(),
|
||||||
|
Some(ast),
|
||||||
));
|
));
|
||||||
|
|
||||||
// return
|
// return
|
||||||
@ -299,8 +303,7 @@ impl TopLevelComposer {
|
|||||||
let primitives = &self.primitives;
|
let primitives = &self.primitives;
|
||||||
let unifier = &mut self.unifier;
|
let unifier = &mut self.unifier;
|
||||||
|
|
||||||
for (class_def, class_ast) in def_list.iter_mut()
|
for (class_def, class_ast) in def_list.iter_mut() {
|
||||||
{
|
|
||||||
// only deal with class def here
|
// only deal with class def here
|
||||||
let mut class_def = class_def.write();
|
let mut class_def = class_def.write();
|
||||||
let (class_bases_ast, class_def_type_vars, class_resolver) = {
|
let (class_bases_ast, class_def_type_vars, class_resolver) = {
|
||||||
@ -327,8 +330,8 @@ impl TopLevelComposer {
|
|||||||
// things like `class A(Generic[T, V, ImportedModule.T])` is not supported
|
// things like `class A(Generic[T, V, ImportedModule.T])` is not supported
|
||||||
// i.e. only simple names are allowed in the subscript
|
// 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, .. }
|
ast::ExprKind::Subscript { value, slice, .. } if matches!(&value.node, ast::ExprKind::Name { id, .. } if id == "Generic") =>
|
||||||
if matches!(&value.node, ast::ExprKind::Name { id, .. } if id == "Generic") => {
|
{
|
||||||
if !is_generic {
|
if !is_generic {
|
||||||
is_generic = true;
|
is_generic = true;
|
||||||
} else {
|
} else {
|
||||||
@ -370,13 +373,12 @@ impl TopLevelComposer {
|
|||||||
|
|
||||||
// `class A(Generic[T])`
|
// `class A(Generic[T])`
|
||||||
} else {
|
} else {
|
||||||
let ty =
|
let ty = class_resolver.parse_type_annotation(
|
||||||
class_resolver.parse_type_annotation(
|
converted_top_level,
|
||||||
converted_top_level,
|
unifier.borrow_mut(),
|
||||||
unifier.borrow_mut(),
|
primitives,
|
||||||
primitives,
|
&slice,
|
||||||
&slice,
|
)?;
|
||||||
)?;
|
|
||||||
// check if it is type var
|
// check if it is type var
|
||||||
let is_type_var =
|
let is_type_var =
|
||||||
matches!(unifier.get_ty(ty).as_ref(), &TypeEnum::TVar { .. });
|
matches!(unifier.get_ty(ty).as_ref(), &TypeEnum::TVar { .. });
|
||||||
@ -408,8 +410,7 @@ impl TopLevelComposer {
|
|||||||
let primitives = &self.primitives;
|
let primitives = &self.primitives;
|
||||||
let unifier = &mut self.unifier;
|
let unifier = &mut self.unifier;
|
||||||
|
|
||||||
for (class_def, class_ast) in def_list.iter_mut()
|
for (class_def, class_ast) in def_list.iter_mut() {
|
||||||
{
|
|
||||||
let mut class_def = class_def.write();
|
let mut class_def = class_def.write();
|
||||||
let (class_bases, class_ancestors, class_resolver) = {
|
let (class_bases, class_ancestors, class_resolver) = {
|
||||||
if let TopLevelDef::Class { ancestors, resolver, .. } = class_def.deref_mut() {
|
if let TopLevelDef::Class { ancestors, resolver, .. } = class_def.deref_mut() {
|
||||||
@ -453,7 +454,7 @@ impl TopLevelComposer {
|
|||||||
if !class_ancestors.contains(&base_id) {
|
if !class_ancestors.contains(&base_id) {
|
||||||
class_ancestors.push(base_id);
|
class_ancestors.push(base_id);
|
||||||
} else {
|
} else {
|
||||||
return Err("cannot specify the same base class twice".into())
|
return Err("cannot specify the same base class twice".into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -471,8 +472,10 @@ impl TopLevelComposer {
|
|||||||
let to_be_analyzed_class = &mut self.to_be_analyzed_class;
|
let to_be_analyzed_class = &mut self.to_be_analyzed_class;
|
||||||
let unifier = &mut self.unifier;
|
let unifier = &mut self.unifier;
|
||||||
|
|
||||||
'class: loop{
|
'class: loop {
|
||||||
if to_be_analyzed_class.is_empty() { break; }
|
if to_be_analyzed_class.is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
let class_ind = to_be_analyzed_class.remove(0).0;
|
let class_ind = to_be_analyzed_class.remove(0).0;
|
||||||
let (class_name, class_body, class_resolver) = {
|
let (class_name, class_body, class_resolver) = {
|
||||||
@ -483,7 +486,9 @@ impl TopLevelComposer {
|
|||||||
{
|
{
|
||||||
if let TopLevelDef::Class { resolver, .. } = class_def.write().deref() {
|
if let TopLevelDef::Class { resolver, .. } = class_def.write().deref() {
|
||||||
(name, body, resolver.as_ref().unwrap().clone())
|
(name, body, resolver.as_ref().unwrap().clone())
|
||||||
} else { unreachable!() }
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
unreachable!("should be class def ast")
|
unreachable!("should be class def ast")
|
||||||
}
|
}
|
||||||
@ -511,16 +516,17 @@ impl TopLevelComposer {
|
|||||||
.annotation
|
.annotation
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
"type annotation for function parameter is needed".to_string()
|
"type annotation for function parameter is needed"
|
||||||
})?.as_ref();
|
.to_string()
|
||||||
|
})?
|
||||||
|
.as_ref();
|
||||||
|
|
||||||
let ty =
|
let ty = class_resolver.as_ref().lock().parse_type_annotation(
|
||||||
class_resolver.as_ref().lock().parse_type_annotation(
|
converted_top_level,
|
||||||
converted_top_level,
|
unifier.borrow_mut(),
|
||||||
unifier.borrow_mut(),
|
primitives,
|
||||||
primitives,
|
annotation,
|
||||||
annotation,
|
)?;
|
||||||
)?;
|
|
||||||
if !Self::check_ty_analyzed(ty, unifier, to_be_analyzed_class) {
|
if !Self::check_ty_analyzed(ty, unifier, to_be_analyzed_class) {
|
||||||
to_be_analyzed_class.push(DefinitionId(class_ind));
|
to_be_analyzed_class.push(DefinitionId(class_ind));
|
||||||
continue 'class;
|
continue 'class;
|
||||||
@ -534,34 +540,37 @@ impl TopLevelComposer {
|
|||||||
result
|
result
|
||||||
};
|
};
|
||||||
|
|
||||||
let method_type_var =
|
let method_type_var = arg_name_tys
|
||||||
arg_name_tys
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(_, ty)| {
|
.filter_map(|(_, ty)| {
|
||||||
let ty_enum = unifier.get_ty(*ty);
|
let ty_enum = unifier.get_ty(*ty);
|
||||||
if let TypeEnum::TVar { id, .. } = ty_enum.as_ref() {
|
if let TypeEnum::TVar { id, .. } = ty_enum.as_ref() {
|
||||||
Some((*id, *ty))
|
Some((*id, *ty))
|
||||||
} else { None }
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect::<Mapping<u32>>();
|
.collect::<Mapping<u32>>();
|
||||||
|
|
||||||
let ret_ty = {
|
let ret_ty = {
|
||||||
if method_name != "__init__" {
|
if method_name != "__init__" {
|
||||||
let ty = method_returns_ast
|
let ty = method_returns_ast
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|x|
|
.map(|x| {
|
||||||
class_resolver.as_ref().lock().parse_type_annotation(
|
class_resolver.as_ref().lock().parse_type_annotation(
|
||||||
converted_top_level,
|
converted_top_level,
|
||||||
unifier.borrow_mut(),
|
unifier.borrow_mut(),
|
||||||
primitives,
|
primitives,
|
||||||
x.as_ref(),
|
x.as_ref(),
|
||||||
)
|
)
|
||||||
)
|
})
|
||||||
.ok_or_else(|| "return type annotation error".to_string())??;
|
.ok_or_else(|| "return type annotation error".to_string())??;
|
||||||
if !Self::check_ty_analyzed(ty, unifier, to_be_analyzed_class) {
|
if !Self::check_ty_analyzed(ty, unifier, to_be_analyzed_class) {
|
||||||
to_be_analyzed_class.push(DefinitionId(class_ind));
|
to_be_analyzed_class.push(DefinitionId(class_ind));
|
||||||
continue 'class;
|
continue 'class;
|
||||||
} else { ty }
|
} else {
|
||||||
|
ty
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO: __init__ function, self type, how
|
// TODO: __init__ function, self type, how
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
@ -569,85 +578,99 @@ impl TopLevelComposer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// handle fields
|
// handle fields
|
||||||
let class_field_name_tys: Option<Vec<(String, Type)>> =
|
let class_field_name_tys: Option<Vec<(String, Type)>> = if method_name
|
||||||
if method_name == "__init__" {
|
== "__init__"
|
||||||
let mut result: Vec<(String, Type)> = vec![];
|
{
|
||||||
for body in method_body_ast {
|
let mut result: Vec<(String, Type)> = vec![];
|
||||||
match &body.node {
|
for body in method_body_ast {
|
||||||
ast::StmtKind::AnnAssign {
|
match &body.node {
|
||||||
target,
|
ast::StmtKind::AnnAssign { target, annotation, .. }
|
||||||
annotation,
|
if {
|
||||||
..
|
if let ast::ExprKind::Attribute { value, .. } = &target.node
|
||||||
} if {
|
{
|
||||||
if let ast::ExprKind::Attribute {
|
|
||||||
value, ..
|
|
||||||
} = &target.node {
|
|
||||||
matches!(
|
matches!(
|
||||||
&value.node,
|
&value.node,
|
||||||
ast::ExprKind::Name { id, .. } if id == "self")
|
ast::ExprKind::Name { id, .. } if id == "self")
|
||||||
} else { false }
|
} else {
|
||||||
} => {
|
false
|
||||||
let field_ty = class_resolver.as_ref().lock().parse_type_annotation(
|
}
|
||||||
|
} =>
|
||||||
|
{
|
||||||
|
let field_ty =
|
||||||
|
class_resolver.as_ref().lock().parse_type_annotation(
|
||||||
converted_top_level,
|
converted_top_level,
|
||||||
unifier.borrow_mut(),
|
unifier.borrow_mut(),
|
||||||
primitives,
|
primitives,
|
||||||
annotation.as_ref())?;
|
annotation.as_ref(),
|
||||||
if !Self::check_ty_analyzed(field_ty, unifier, to_be_analyzed_class) {
|
)?;
|
||||||
to_be_analyzed_class.push(DefinitionId(class_ind));
|
if !Self::check_ty_analyzed(
|
||||||
continue 'class;
|
field_ty,
|
||||||
} else {
|
unifier,
|
||||||
result.push((
|
to_be_analyzed_class,
|
||||||
if let ast::ExprKind::Attribute {
|
) {
|
||||||
attr, ..
|
to_be_analyzed_class.push(DefinitionId(class_ind));
|
||||||
} = &target.node {
|
continue 'class;
|
||||||
attr.to_string()
|
} else {
|
||||||
} else { unreachable!() },
|
result.push((
|
||||||
field_ty
|
if let ast::ExprKind::Attribute { attr, .. } =
|
||||||
)) }
|
&target.node
|
||||||
},
|
{
|
||||||
|
attr.to_string()
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
},
|
||||||
|
field_ty,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// exclude those without type annotation
|
// exclude those without type annotation
|
||||||
ast::StmtKind::Assign {
|
ast::StmtKind::Assign { targets, .. }
|
||||||
targets, ..
|
if {
|
||||||
} if {
|
if let ast::ExprKind::Attribute { value, .. } =
|
||||||
if let ast::ExprKind::Attribute {
|
&targets[0].node
|
||||||
value, ..
|
{
|
||||||
} = &targets[0].node {
|
|
||||||
matches!(
|
matches!(
|
||||||
&value.node,
|
&value.node,
|
||||||
ast::ExprKind::Name {id, ..} if id == "self")
|
ast::ExprKind::Name {id, ..} if id == "self")
|
||||||
} else { false }
|
} else {
|
||||||
} => {
|
false
|
||||||
return Err("class fields type annotation needed".into())
|
}
|
||||||
},
|
} =>
|
||||||
|
{
|
||||||
// do nothing
|
return Err("class fields type annotation needed".into())
|
||||||
_ => { }
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
Some(result)
|
// do nothing
|
||||||
} else { None };
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(result)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
// current method all type ok, put the current method into the list
|
// current method all type ok, put the current method into the list
|
||||||
if class_methods_parsing_result
|
if class_methods_parsing_result.iter().any(|(name, _, _)| name == method_name) {
|
||||||
.iter()
|
return Err("duplicate method definition".into());
|
||||||
.any(|(name, _, _)| name == method_name) {
|
|
||||||
return Err("duplicate method definition".into())
|
|
||||||
} else {
|
} else {
|
||||||
class_methods_parsing_result.push((
|
class_methods_parsing_result.push((
|
||||||
method_name.clone(),
|
method_name.clone(),
|
||||||
unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
unifier.add_ty(TypeEnum::TFunc(
|
||||||
ret: ret_ty,
|
FunSignature {
|
||||||
args: arg_name_tys.into_iter().map(|(name, ty)| {
|
ret: ret_ty,
|
||||||
FuncArg {
|
args: arg_name_tys
|
||||||
name,
|
.into_iter()
|
||||||
ty,
|
.map(|(name, ty)| FuncArg { name, ty, default_value: None })
|
||||||
default_value: None
|
.collect_vec(),
|
||||||
}
|
vars: method_type_var,
|
||||||
}).collect_vec(),
|
}
|
||||||
vars: method_type_var
|
.into(),
|
||||||
}.into())),
|
)),
|
||||||
*self.class_method_to_def_id.get(&Self::name_mangling(class_name.clone(), method_name)).unwrap()
|
*self
|
||||||
|
.class_method_to_def_id
|
||||||
|
.get(&Self::name_mangling(class_name.clone(), method_name))
|
||||||
|
.unwrap(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -661,7 +684,7 @@ impl TopLevelComposer {
|
|||||||
// do nothing, continue the for loop to iterate class ast
|
// do nothing, continue the for loop to iterate class ast
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// now it should be confirmed that every
|
// now it should be confirmed that every
|
||||||
// methods and fields of the class can be correctly typed, put the results
|
// methods and fields of the class can be correctly typed, put the results
|
||||||
@ -675,7 +698,9 @@ impl TopLevelComposer {
|
|||||||
for (n, t, id) in &class_methods_parsing_result {
|
for (n, t, id) in &class_methods_parsing_result {
|
||||||
methods.push((n.clone(), *t, *id));
|
methods.push((n.clone(), *t, *id));
|
||||||
}
|
}
|
||||||
} else { unreachable!() }
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
// change the signature field of the class methods
|
// change the signature field of the class methods
|
||||||
for (_, ty, id) in &class_methods_parsing_result {
|
for (_, ty, id) in &class_methods_parsing_result {
|
||||||
@ -685,7 +710,7 @@ impl TopLevelComposer {
|
|||||||
*signature = *ty;
|
*signature = *ty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -697,19 +722,12 @@ impl TopLevelComposer {
|
|||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_ty_analyzed(ty: Type,
|
fn check_ty_analyzed(ty: Type, unifier: &mut Unifier, to_be_analyzed: &[DefinitionId]) -> bool {
|
||||||
unifier: &mut Unifier,
|
|
||||||
to_be_analyzed: &[DefinitionId]) -> bool
|
|
||||||
{
|
|
||||||
let type_enum = unifier.get_ty(ty);
|
let type_enum = unifier.get_ty(ty);
|
||||||
match type_enum.as_ref() {
|
match type_enum.as_ref() {
|
||||||
TypeEnum::TObj { obj_id, .. } => {
|
TypeEnum::TObj { obj_id, .. } => !to_be_analyzed.contains(obj_id),
|
||||||
!to_be_analyzed.contains(obj_id)
|
|
||||||
}
|
|
||||||
TypeEnum::TVirtual { ty } => {
|
TypeEnum::TVirtual { ty } => {
|
||||||
if let TypeEnum::TObj { obj_id, .. } =
|
if let TypeEnum::TObj { obj_id, .. } = unifier.get_ty(*ty).as_ref() {
|
||||||
unifier.get_ty(*ty).as_ref()
|
|
||||||
{
|
|
||||||
!to_be_analyzed.contains(obj_id)
|
!to_be_analyzed.contains(obj_id)
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
@ -146,14 +146,17 @@ impl TestEnvironment {
|
|||||||
});
|
});
|
||||||
identifier_mapping.insert("None".into(), none);
|
identifier_mapping.insert("None".into(), none);
|
||||||
for i in 0..5 {
|
for i in 0..5 {
|
||||||
top_level_defs.push(RwLock::new(TopLevelDef::Class {
|
top_level_defs.push(
|
||||||
object_id: DefinitionId(i),
|
RwLock::new(TopLevelDef::Class {
|
||||||
type_vars: Default::default(),
|
object_id: DefinitionId(i),
|
||||||
fields: Default::default(),
|
type_vars: Default::default(),
|
||||||
methods: Default::default(),
|
fields: Default::default(),
|
||||||
ancestors: Default::default(),
|
methods: Default::default(),
|
||||||
resolver: None,
|
ancestors: Default::default(),
|
||||||
}).into());
|
resolver: None,
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let primitives = PrimitiveStore { int32, int64, float, bool, none };
|
let primitives = PrimitiveStore { int32, int64, float, bool, none };
|
||||||
@ -165,14 +168,17 @@ impl TestEnvironment {
|
|||||||
fields: [("a".into(), v0)].iter().cloned().collect::<HashMap<_, _>>().into(),
|
fields: [("a".into(), v0)].iter().cloned().collect::<HashMap<_, _>>().into(),
|
||||||
params: [(id, v0)].iter().cloned().collect::<HashMap<_, _>>().into(),
|
params: [(id, v0)].iter().cloned().collect::<HashMap<_, _>>().into(),
|
||||||
});
|
});
|
||||||
top_level_defs.push(RwLock::new(TopLevelDef::Class {
|
top_level_defs.push(
|
||||||
object_id: DefinitionId(5),
|
RwLock::new(TopLevelDef::Class {
|
||||||
type_vars: vec![v0],
|
object_id: DefinitionId(5),
|
||||||
fields: [("a".into(), v0)].into(),
|
type_vars: vec![v0],
|
||||||
methods: Default::default(),
|
fields: [("a".into(), v0)].into(),
|
||||||
ancestors: Default::default(),
|
methods: Default::default(),
|
||||||
resolver: None,
|
ancestors: Default::default(),
|
||||||
}).into());
|
resolver: None,
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
identifier_mapping.insert(
|
identifier_mapping.insert(
|
||||||
"Foo".into(),
|
"Foo".into(),
|
||||||
@ -198,14 +204,17 @@ impl TestEnvironment {
|
|||||||
.into(),
|
.into(),
|
||||||
params: Default::default(),
|
params: Default::default(),
|
||||||
});
|
});
|
||||||
top_level_defs.push(RwLock::new(TopLevelDef::Class {
|
top_level_defs.push(
|
||||||
object_id: DefinitionId(6),
|
RwLock::new(TopLevelDef::Class {
|
||||||
type_vars: Default::default(),
|
object_id: DefinitionId(6),
|
||||||
fields: [("a".into(), int32), ("b".into(), fun)].into(),
|
type_vars: Default::default(),
|
||||||
methods: Default::default(),
|
fields: [("a".into(), int32), ("b".into(), fun)].into(),
|
||||||
ancestors: Default::default(),
|
methods: Default::default(),
|
||||||
resolver: None,
|
ancestors: Default::default(),
|
||||||
}).into());
|
resolver: None,
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
identifier_mapping.insert(
|
identifier_mapping.insert(
|
||||||
"Bar".into(),
|
"Bar".into(),
|
||||||
unifier.add_ty(TypeEnum::TFunc(
|
unifier.add_ty(TypeEnum::TFunc(
|
||||||
@ -222,14 +231,17 @@ impl TestEnvironment {
|
|||||||
.into(),
|
.into(),
|
||||||
params: Default::default(),
|
params: Default::default(),
|
||||||
});
|
});
|
||||||
top_level_defs.push(RwLock::new(TopLevelDef::Class {
|
top_level_defs.push(
|
||||||
object_id: DefinitionId(7),
|
RwLock::new(TopLevelDef::Class {
|
||||||
type_vars: Default::default(),
|
object_id: DefinitionId(7),
|
||||||
fields: [("a".into(), bool), ("b".into(), fun)].into(),
|
type_vars: Default::default(),
|
||||||
methods: Default::default(),
|
fields: [("a".into(), bool), ("b".into(), fun)].into(),
|
||||||
ancestors: Default::default(),
|
methods: Default::default(),
|
||||||
resolver: None,
|
ancestors: Default::default(),
|
||||||
}).into());
|
resolver: None,
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
identifier_mapping.insert(
|
identifier_mapping.insert(
|
||||||
"Bar2".into(),
|
"Bar2".into(),
|
||||||
unifier.add_ty(TypeEnum::TFunc(
|
unifier.add_ty(TypeEnum::TFunc(
|
||||||
|
Loading…
Reference in New Issue
Block a user