forked from M-Labs/nac3
1
0
Fork 0

formating

This commit is contained in:
ychenfo 2021-08-18 16:33:50 +08:00
parent 529442590f
commit 6279dbb589
2 changed files with 213 additions and 183 deletions

View File

@ -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,12 +262,10 @@ 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
@ -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(
name.into(),
self.primitives.none,
resolver,
))
.into(), .into(),
Some(ast) 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,8 +373,7 @@ 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,
@ -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,11 +516,12 @@ 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,
@ -534,14 +540,15 @@ 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>>();
@ -549,19 +556,21 @@ impl TopLevelComposer {
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![]; let mut result: Vec<(String, Type)> = vec![];
for body in method_body_ast { for body in method_body_ast {
match &body.node { match &body.node {
ast::StmtKind::AnnAssign { ast::StmtKind::AnnAssign { target, annotation, .. }
target, if {
annotation, 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) { )?;
if !Self::check_ty_analyzed(
field_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 { } else {
result.push(( result.push((
if let ast::ExprKind::Attribute { if let ast::ExprKind::Attribute { attr, .. } =
attr, .. &target.node
} = &target.node { {
attr.to_string() attr.to_string()
} else { unreachable!() }, } else {
field_ty 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()) return Err("class fields type annotation needed".into())
}, }
// do nothing // do nothing
_ => { } _ => {}
}
} }
};
Some(result) Some(result)
} else { None }; } 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(
FunSignature {
ret: ret_ty, ret: ret_ty,
args: arg_name_tys.into_iter().map(|(name, ty)| { args: arg_name_tys
FuncArg { .into_iter()
name, .map(|(name, ty)| FuncArg { name, ty, default_value: None })
ty, .collect_vec(),
default_value: None vars: method_type_var,
} }
}).collect_vec(), .into(),
vars: method_type_var )),
}.into())), *self
*self.class_method_to_def_id.get(&Self::name_mangling(class_name.clone(), method_name)).unwrap() .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!()

View File

@ -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(
RwLock::new(TopLevelDef::Class {
object_id: DefinitionId(i), object_id: DefinitionId(i),
type_vars: Default::default(), type_vars: Default::default(),
fields: Default::default(), fields: Default::default(),
methods: Default::default(), methods: Default::default(),
ancestors: Default::default(), ancestors: Default::default(),
resolver: None, resolver: None,
}).into()); })
.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(
RwLock::new(TopLevelDef::Class {
object_id: DefinitionId(5), object_id: DefinitionId(5),
type_vars: vec![v0], type_vars: vec![v0],
fields: [("a".into(), v0)].into(), fields: [("a".into(), v0)].into(),
methods: Default::default(), methods: Default::default(),
ancestors: Default::default(), ancestors: Default::default(),
resolver: None, resolver: None,
}).into()); })
.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(
RwLock::new(TopLevelDef::Class {
object_id: DefinitionId(6), object_id: DefinitionId(6),
type_vars: Default::default(), type_vars: Default::default(),
fields: [("a".into(), int32), ("b".into(), fun)].into(), fields: [("a".into(), int32), ("b".into(), fun)].into(),
methods: Default::default(), methods: Default::default(),
ancestors: Default::default(), ancestors: Default::default(),
resolver: None, resolver: None,
}).into()); })
.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(
RwLock::new(TopLevelDef::Class {
object_id: DefinitionId(7), object_id: DefinitionId(7),
type_vars: Default::default(), type_vars: Default::default(),
fields: [("a".into(), bool), ("b".into(), fun)].into(), fields: [("a".into(), bool), ("b".into(), fun)].into(),
methods: Default::default(), methods: Default::default(),
ancestors: Default::default(), ancestors: Default::default(),
resolver: None, resolver: None,
}).into()); })
.into(),
);
identifier_mapping.insert( identifier_mapping.insert(
"Bar2".into(), "Bar2".into(),
unifier.add_ty(TypeEnum::TFunc( unifier.add_ty(TypeEnum::TFunc(