From 87f25e1c5db3be08683e5e9413471e2c2eed012e Mon Sep 17 00:00:00 2001 From: ychenfo Date: Wed, 8 Sep 2021 19:27:32 +0800 Subject: [PATCH] nac3core: remove mutex on dyn symbol resolve --- nac3core/src/codegen/expr.rs | 2 +- nac3core/src/codegen/mod.rs | 4 +- nac3core/src/codegen/test.rs | 10 +-- nac3core/src/symbol_resolver.rs | 1 - nac3core/src/toplevel/helper.rs | 4 +- nac3core/src/toplevel/mod.rs | 61 +++++++++---- nac3core/src/toplevel/test.rs | 85 ++++++++++++------- nac3core/src/toplevel/type_annotation.rs | 24 ++++-- nac3core/src/typecheck/function_check.rs | 2 +- nac3core/src/typecheck/type_inferencer/mod.rs | 11 ++- .../src/typecheck/type_inferencer/test.rs | 12 +-- nac3standalone/src/basic_symbol_resolver.rs | 4 - nac3standalone/src/main.rs | 6 +- 13 files changed, 136 insertions(+), 90 deletions(-) diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs index dc44a524e..91656ec5c 100644 --- a/nac3core/src/codegen/expr.rs +++ b/nac3core/src/codegen/expr.rs @@ -610,7 +610,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> { if let ExprKind::Name { id, .. } = &func.as_ref().node { // TODO: handle primitive casts and function pointers let fun = - self.resolver.lock().get_identifier_def(&id).expect("Unknown identifier"); + self.resolver.get_identifier_def(&id).expect("Unknown identifier"); let mut params = args.iter().map(|arg| (None, self.gen_expr(arg).unwrap())).collect_vec(); let kw_iter = keywords.iter().map(|kw| { diff --git a/nac3core/src/codegen/mod.rs b/nac3core/src/codegen/mod.rs index 79c96997d..ccedbe5de 100644 --- a/nac3core/src/codegen/mod.rs +++ b/nac3core/src/codegen/mod.rs @@ -38,7 +38,7 @@ pub struct CodeGenContext<'ctx, 'a> { pub module: Module<'ctx>, pub top_level: &'a TopLevelContext, pub unifier: Unifier, - pub resolver: Arc>>, + pub resolver: Arc>, pub var_assignment: HashMap>, pub type_cache: HashMap>, pub primitives: PrimitiveStore, @@ -190,7 +190,7 @@ pub struct CodeGenTask { pub body: Vec>>, pub calls: HashMap, pub unifier: (SharedUnifier, PrimitiveStore), - pub resolver: Arc>>, + pub resolver: Arc>, } fn get_llvm_type<'ctx>( diff --git a/nac3core/src/codegen/test.rs b/nac3core/src/codegen/test.rs index dd61ae118..4d6d99eb1 100644 --- a/nac3core/src/codegen/test.rs +++ b/nac3core/src/codegen/test.rs @@ -43,10 +43,6 @@ impl SymbolResolver for Resolver { fn get_identifier_def(&self, id: &str) -> Option { self.id_to_def.read().get(id).cloned() } - - fn add_id_def(&mut self, _: String, _: DefinitionId) { - unimplemented!() - } } #[test] @@ -70,11 +66,11 @@ fn test_primitives() { // class_names: Default::default(), // }) as Mutex); - let resolver = Arc::new(Mutex::new(Box::new(Resolver { + let resolver = Arc::new(Box::new(Resolver { id_to_type: HashMap::new(), id_to_def: RwLock::new(HashMap::new()), class_names: Default::default(), - }) as Box)); + }) as Box); let threads = ["test"]; let signature = FunSignature { @@ -236,7 +232,7 @@ fn test_simple_call() { class_names: Default::default(), }); resolver.add_id_def("foo".to_string(), DefinitionId(foo_id)); - let resolver = Arc::new(Mutex::new(resolver as Box)); + let resolver = Arc::new(resolver as Box); if let TopLevelDef::Function { resolver: r, .. } = &mut *top_level.definitions.read()[foo_id].write() diff --git a/nac3core/src/symbol_resolver.rs b/nac3core/src/symbol_resolver.rs index a015d2595..e28e2c7fe 100644 --- a/nac3core/src/symbol_resolver.rs +++ b/nac3core/src/symbol_resolver.rs @@ -35,7 +35,6 @@ pub trait SymbolResolver { fn get_identifier_def(&self, str: &str) -> Option; fn get_symbol_value(&self, str: &str) -> Option; fn get_symbol_location(&self, str: &str) -> Option; - fn add_id_def(&mut self, id: String, def_id: DefinitionId); // handle function call etc. } diff --git a/nac3core/src/toplevel/helper.rs b/nac3core/src/toplevel/helper.rs index ffdea0b17..73325ad5b 100644 --- a/nac3core/src/toplevel/helper.rs +++ b/nac3core/src/toplevel/helper.rs @@ -87,7 +87,7 @@ impl TopLevelComposer { /// when first regitering, the type_vars, fields, methods, ancestors are invalid pub fn make_top_level_class_def( index: usize, - resolver: Option>>>, + resolver: Option>>, name: &str, ) -> TopLevelDef { TopLevelDef::Class { @@ -105,7 +105,7 @@ impl TopLevelComposer { pub fn make_top_level_function_def( name: String, ty: Type, - resolver: Option>>>, + resolver: Option>>, ) -> TopLevelDef { TopLevelDef::Function { name, diff --git a/nac3core/src/toplevel/mod.rs b/nac3core/src/toplevel/mod.rs index e254febb7..2cae75605 100644 --- a/nac3core/src/toplevel/mod.rs +++ b/nac3core/src/toplevel/mod.rs @@ -1,11 +1,4 @@ -use std::{ - borrow::BorrowMut, - collections::{HashMap, HashSet}, - fmt::Debug, - iter::FromIterator, - ops::{Deref, DerefMut}, - sync::Arc, -}; +use std::{borrow::BorrowMut, collections::{HashMap, HashSet}, fmt::Debug, iter::FromIterator, ops::{Deref, DerefMut}, sync::Arc}; use super::typecheck::type_inferencer::PrimitiveStore; use super::typecheck::typedef::{FunSignature, FuncArg, SharedUnifier, Type, TypeEnum, Unifier}; @@ -50,7 +43,7 @@ pub enum TopLevelDef { // ancestor classes, including itself. ancestors: Vec, // symbol resolver of the module defined the class, none if it is built-in type - resolver: Option>>>, + resolver: Option>>, }, Function { // prefix for symbol, should be unique globally, and not ending with numbers @@ -71,7 +64,7 @@ pub enum TopLevelDef { /// rigid type variables that would be substituted when the function is instantiated. instance_to_stmt: HashMap, // symbol resolver of the module defined the class - resolver: Option>>>, + resolver: Option>>, }, Initializer { class_id: DefinitionId, @@ -162,7 +155,7 @@ impl TopLevelComposer { pub fn register_top_level( &mut self, ast: ast::Stmt<()>, - resolver: Option>>>, + resolver: Option>>, ) -> Result<(String, DefinitionId), String> { let defined_class_name = &mut self.defined_class_name; let defined_class_method_name = &mut self.defined_class_method_name; @@ -374,7 +367,7 @@ impl TopLevelComposer { let type_vars = type_var_list .into_iter() .map(|e| { - class_resolver.lock().parse_type_annotation( + class_resolver.parse_type_annotation( &temp_def_list, unifier, primitives_store, @@ -463,7 +456,7 @@ impl TopLevelComposer { // the function parse_ast_to make sure that no type var occured in // bast_ty if it is a CustomClassKind let base_ty = parse_ast_to_type_annotation_kinds( - class_resolver, + class_resolver.as_ref(), &temp_def_list, unifier, &self.primitives_ty, @@ -550,6 +543,8 @@ impl TopLevelComposer { } } + println!("type_var_to_concrete_def1: {:?}", type_var_to_concrete_def); + // handle the inheritanced methods and fields let mut current_ancestor_depth: usize = 2; loop { @@ -584,11 +579,41 @@ impl TopLevelComposer { } } + // println!("type_var_to_concrete_def2: {:?}", type_var_to_concrete_def); + // unification of previously assigned typevar + println!("type_var_to_concrete_def3: {:?}\n", type_var_to_concrete_def); + let mut ddddd: Vec<(Type, Type)> = Vec::new(); for (ty, def) in type_var_to_concrete_def { + println!( + "{:?}_{} -> {:?}\n", + ty, + unifier.stringify(ty, + &mut |id| format!("class{}", id), + &mut |id| format!("tvar{}", id) + ), + def + ); let target_ty = get_type_from_type_annotation_kinds(&temp_def_list, unifier, primitives, &def)?; unifier.unify(ty, target_ty)?; + ddddd.push((ty, target_ty)); + } + + for (ty, tar_ty) in ddddd { + println!( + "{:?}_{} -> {:?}_{}", + ty, + unifier.stringify(ty, + &mut |id| format!("class{}", id), + &mut |id| format!("tvar{}", id) + ), + tar_ty, + unifier.stringify(tar_ty, + &mut |id| format!("class{}", id), + &mut |id| format!("tvar{}", id) + ), + ) } Ok(()) @@ -649,7 +674,7 @@ impl TopLevelComposer { .as_ref(); let type_annotation = parse_ast_to_type_annotation_kinds( - resolver, + resolver.as_ref(), temp_def_list.as_slice(), unifier, primitives_store, @@ -695,7 +720,7 @@ impl TopLevelComposer { let return_ty_annotation = { let return_annotation = returns.as_ref(); parse_ast_to_type_annotation_kinds( - resolver, + resolver.as_ref(), &temp_def_list, unifier, primitives_store, @@ -848,7 +873,7 @@ impl TopLevelComposer { .ok_or_else(|| "type annotation needed".to_string())? .as_ref(); parse_ast_to_type_annotation_kinds( - class_resolver, + class_resolver.as_ref(), temp_def_list, unifier, primitives, @@ -908,7 +933,7 @@ impl TopLevelComposer { if let Some(result) = returns { let result = result.as_ref(); let annotation = parse_ast_to_type_annotation_kinds( - class_resolver, + class_resolver.as_ref(), temp_def_list, unifier, primitives, @@ -986,7 +1011,7 @@ impl TopLevelComposer { class_fields_def.push((attr.to_string(), dummy_field_type)); let annotation = parse_ast_to_type_annotation_kinds( - class_resolver, + class_resolver.as_ref(), &temp_def_list, unifier, primitives, diff --git a/nac3core/src/toplevel/test.rs b/nac3core/src/toplevel/test.rs index e48e94c01..4337ef9a2 100644 --- a/nac3core/src/toplevel/test.rs +++ b/nac3core/src/toplevel/test.rs @@ -15,15 +15,23 @@ use test_case::test_case; use super::*; -struct Resolver { - id_to_type: HashMap, - id_to_def: HashMap, - class_names: HashMap, +struct ResolverInternal { + id_to_type: Mutex>, + id_to_def: Mutex>, + class_names: Mutex>, } +impl ResolverInternal { + fn add_id_def(&self, id: String, def: DefinitionId) { + self.id_to_def.lock().insert(id, def); + } +} + +struct Resolver(Arc); + impl SymbolResolver for Resolver { fn get_symbol_type(&self, _: &mut Unifier, _: &PrimitiveStore, str: &str) -> Option { - self.id_to_type.get(str).cloned() + self.0.id_to_type.lock().get(str).cloned() } fn get_symbol_value(&self, _: &str) -> Option { @@ -35,12 +43,9 @@ impl SymbolResolver for Resolver { } fn get_identifier_def(&self, id: &str) -> Option { - self.id_to_def.get(id).cloned() + self.0.id_to_def.lock().get(id).cloned() } - fn add_id_def(&mut self, id: String, def: DefinitionId) { - self.id_to_def.insert(id, def); - } } #[test_case( @@ -72,7 +77,8 @@ impl SymbolResolver for Resolver { self.c: int32 = 4 self.a: bool = True "} - ] + ]; + "register" )] fn test_simple_register(source: Vec<&str>) { let mut composer = TopLevelComposer::new(); @@ -109,23 +115,25 @@ fn test_simple_register(source: Vec<&str>) { "fun", "foo", "f" - ] + ]; + "function compose" )] fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&str>) { let mut composer = TopLevelComposer::new(); - let resolver = Arc::new(Mutex::new(Box::new(Resolver { + let internal_resolver = Arc::new(ResolverInternal { id_to_def: Default::default(), id_to_type: Default::default(), class_names: Default::default(), - }) as Box)); + }); + let resolver = Arc::new(Box::new(Resolver(internal_resolver.clone())) as Box); for s in source { let ast = parse_program(s).unwrap(); let ast = ast[0].clone(); let (id, def_id) = composer.register_top_level(ast, Some(resolver.clone())).unwrap(); - resolver.lock().add_id_def(id, def_id); + internal_resolver.add_id_def(id, def_id); } composer.start_analysis().unwrap(); @@ -245,7 +253,19 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s sig: \"fn[[a=5], 4]\", var_id: [] }"}, - ] + ]; + "simple class compose" +)] +#[test_case( + vec![ + indoc! {" + class Generic_A(Generic[T, V]): + def __init__(): + pass + "} + ], + vec![]; + "generic class" )] fn test_simple_class_analyze(source: Vec<&str>, res: Vec<&str>) { let mut composer = TopLevelComposer::new(); @@ -254,23 +274,24 @@ fn test_simple_class_analyze(source: Vec<&str>, res: Vec<&str>) { let tvar_v = composer .unifier .get_fresh_var_with_range(&[composer.primitives_ty.bool, composer.primitives_ty.int32]); - println!("t: {}", tvar_t.1); - println!("v: {}\n", tvar_v.1); + println!("t: {}, {:?}", tvar_t.1, tvar_t.0); + println!("v: {}, {:?}\n", tvar_v.1, tvar_v.0); - let resolver = Arc::new(Mutex::new(Box::new(Resolver { + let internal_resolver = Arc::new(ResolverInternal { id_to_def: Default::default(), - id_to_type: vec![("T".to_string(), tvar_t.0), ("V".to_string(), tvar_v.0)] - .into_iter() - .collect(), + id_to_type: Mutex::new(vec![("T".to_string(), tvar_t.0), ("V".to_string(), tvar_v.0)] + .into_iter() + .collect()), class_names: Default::default(), - }) as Box)); + }); + let resolver = Arc::new(Box::new(Resolver(internal_resolver.clone())) as Box); for s in source { let ast = parse_program(s).unwrap(); let ast = ast[0].clone(); let (id, def_id) = composer.register_top_level(ast, Some(resolver.clone())).unwrap(); - resolver.lock().add_id_def(id, def_id); + internal_resolver.add_id_def(id, def_id); } composer.start_analysis().unwrap(); @@ -278,15 +299,15 @@ fn test_simple_class_analyze(source: Vec<&str>, res: Vec<&str>) { // skip 5 to skip primitives for (i, (def, _)) in composer.definition_ast_list.iter().skip(5).enumerate() { let def = &*def.read(); - println!( - "{}: {}\n", - i + 5, - def.to_string( - composer.unifier.borrow_mut(), - &mut |id| format!("class{}", id), - &mut |id| format!("tvar{}", id) - ) - ); + // println!( + // "{}: {}\n", + // i + 5, + // def.to_string( + // composer.unifier.borrow_mut(), + // &mut |id| format!("class{}", id), + // &mut |id| format!("tvar{}", id) + // ) + // ); // assert_eq!( // format!( // "{}: {}", diff --git a/nac3core/src/toplevel/type_annotation.rs b/nac3core/src/toplevel/type_annotation.rs index 38345050e..291937fc8 100644 --- a/nac3core/src/toplevel/type_annotation.rs +++ b/nac3core/src/toplevel/type_annotation.rs @@ -1,3 +1,5 @@ +use std::cell::RefCell; + use crate::typecheck::typedef::TypeVarMeta; use super::*; @@ -19,7 +21,7 @@ pub enum TypeAnnotation { } pub fn parse_ast_to_type_annotation_kinds( - resolver: &Mutex>, + resolver: &(dyn SymbolResolver + Send + Sync), top_level_defs: &[Arc>], unifier: &mut Unifier, primitives: &PrimitiveStore, @@ -36,7 +38,7 @@ pub fn parse_ast_to_type_annotation_kinds( if let Some(obj_id) = { // write this way because the lock in the if/let construct lives // for the whole if let construct - let id = resolver.lock().get_identifier_def(x); + let id = resolver.get_identifier_def(x); id } { let def = top_level_defs[obj_id.0].read(); @@ -53,7 +55,7 @@ pub fn parse_ast_to_type_annotation_kinds( Err("function cannot be used as a type".into()) } } else if let Some(ty) = { - let ty = resolver.lock().get_symbol_type(unifier, primitives, id); + let ty = resolver.get_symbol_type(unifier, primitives, id); ty } { if let TypeEnum::TVar { .. } = unifier.get_ty(ty).as_ref() { @@ -128,7 +130,6 @@ pub fn parse_ast_to_type_annotation_kinds( return Err("keywords cannot be class name".into()); } let obj_id = resolver - .lock() .get_identifier_def(id) .ok_or_else(|| "unknown class name".to_string())?; let def = top_level_defs[obj_id.0].read(); @@ -237,9 +238,22 @@ pub fn get_type_from_type_annotation_kinds( let subst_ty = unifier.subst(*ty, &subst).unwrap_or(*ty); (name.clone(), subst_ty) })); + + println!("tobj_fields: {:?}", tobj_fields); + println!("{:?}: {}\n", + tobj_fields.get("__init__").unwrap(), + unifier.stringify( + *tobj_fields.get("__init__").unwrap(), + &mut |id| format!("class{}", id), + &mut |id| format!("tvar{}", id) + ) + ); + Ok(unifier.add_ty(TypeEnum::TObj { obj_id: *id, - fields: tobj_fields.into(), + //fields: RefCell::new(tobj_fields), + fields: RefCell::new(HashMap::new()), + // fields: Default::default(), params: subst.into(), })) } diff --git a/nac3core/src/typecheck/function_check.rs b/nac3core/src/typecheck/function_check.rs index 4988a3dc5..033066151 100644 --- a/nac3core/src/typecheck/function_check.rs +++ b/nac3core/src/typecheck/function_check.rs @@ -57,7 +57,7 @@ impl<'a> Inferencer<'a> { match &expr.node { ExprKind::Name { id, .. } => { if !defined_identifiers.contains(id) { - if self.function_data.resolver.lock().get_identifier_def(id).is_some() { + if self.function_data.resolver.get_identifier_def(id).is_some() { defined_identifiers.insert(id.clone()); } else { return Err(format!( diff --git a/nac3core/src/typecheck/type_inferencer/mod.rs b/nac3core/src/typecheck/type_inferencer/mod.rs index 68a3d4d9d..57e19b009 100644 --- a/nac3core/src/typecheck/type_inferencer/mod.rs +++ b/nac3core/src/typecheck/type_inferencer/mod.rs @@ -39,7 +39,7 @@ pub struct PrimitiveStore { } pub struct FunctionData { - pub resolver: Arc>>, + pub resolver: Arc>, pub return_type: Option, pub bound_variables: Vec, } @@ -89,7 +89,7 @@ impl<'a> fold::Fold<()> for Inferencer<'a> { )); }; let top_level_defs = self.top_level.definitions.read(); - let annotation_type = self.function_data.resolver.lock().parse_type_annotation( + let annotation_type = self.function_data.resolver.parse_type_annotation( top_level_defs.as_slice(), self.unifier, &self.primitives, @@ -164,7 +164,7 @@ impl<'a> fold::Fold<()> for Inferencer<'a> { ast::ExprKind::Constant { value, .. } => Some(self.infer_constant(value)?), ast::ExprKind::Name { id, .. } => { if !self.defined_identifiers.contains(id) { - if self.function_data.resolver.lock().get_identifier_def(id.as_str()).is_some() + if self.function_data.resolver.get_identifier_def(id.as_str()).is_some() { self.defined_identifiers.insert(id.clone()); } else { @@ -405,7 +405,7 @@ impl<'a> Inferencer<'a> { let arg0 = self.fold_expr(args.remove(0))?; let ty = if let Some(arg) = args.pop() { let top_level_defs = self.top_level.definitions.read(); - self.function_data.resolver.lock().parse_type_annotation( + self.function_data.resolver.parse_type_annotation( top_level_defs.as_slice(), self.unifier, self.primitives, @@ -483,10 +483,9 @@ impl<'a> Inferencer<'a> { if let Some(ty) = self.variable_mapping.get(id) { Ok(*ty) } else { - let resolver = self.function_data.resolver.lock(); let variable_mapping = &mut self.variable_mapping; let unifier = &mut self.unifier; - Ok(resolver.get_symbol_type(unifier, self.primitives, id).unwrap_or_else(|| { + Ok(self.function_data.resolver.get_symbol_type(unifier, self.primitives, id).unwrap_or_else(|| { let ty = unifier.get_fresh_var().0; variable_mapping.insert(id.to_string(), ty); ty diff --git a/nac3core/src/typecheck/type_inferencer/test.rs b/nac3core/src/typecheck/type_inferencer/test.rs index 3a507bd6c..bf1c37275 100644 --- a/nac3core/src/typecheck/type_inferencer/test.rs +++ b/nac3core/src/typecheck/type_inferencer/test.rs @@ -33,10 +33,6 @@ impl SymbolResolver for Resolver { fn get_identifier_def(&self, id: &str) -> Option { self.id_to_def.get(id).cloned() } - - fn add_id_def(&mut self, _: String, _: DefinitionId) { - unimplemented!() - } } struct TestEnvironment { @@ -96,11 +92,11 @@ impl TestEnvironment { let mut identifier_mapping = HashMap::new(); identifier_mapping.insert("None".into(), none); - let resolver = Arc::new(Mutex::new(Box::new(Resolver { + let resolver = Arc::new(Box::new(Resolver { id_to_type: identifier_mapping.clone(), id_to_def: Default::default(), class_names: Default::default(), - }) as Box)); + }) as Box); TestEnvironment { top_level: TopLevelContext { @@ -279,7 +275,7 @@ impl TestEnvironment { unifiers: Default::default(), }; - let resolver = Arc::new(Mutex::new(Box::new(Resolver { + let resolver = Arc::new(Box::new(Resolver { id_to_type: identifier_mapping.clone(), id_to_def: [ ("Foo".into(), DefinitionId(5)), @@ -290,7 +286,7 @@ impl TestEnvironment { .cloned() .collect(), class_names, - }) as Box)); + }) as Box); TestEnvironment { unifier, diff --git a/nac3standalone/src/basic_symbol_resolver.rs b/nac3standalone/src/basic_symbol_resolver.rs index b74c27fd6..8b0a16d2f 100644 --- a/nac3standalone/src/basic_symbol_resolver.rs +++ b/nac3standalone/src/basic_symbol_resolver.rs @@ -32,8 +32,4 @@ impl SymbolResolver for Resolver { fn get_identifier_def(&self, id: &str) -> Option { self.id_to_def.get(id).cloned() } - - fn add_id_def(&mut self, _: String, _: DefinitionId) { - unimplemented!(); - } } diff --git a/nac3standalone/src/main.rs b/nac3standalone/src/main.rs index 682ca3037..06ee2a2ae 100644 --- a/nac3standalone/src/main.rs +++ b/nac3standalone/src/main.rs @@ -164,11 +164,11 @@ fn main() { .collect(); id_to_type.insert("output".into(), output_fun); - let resolver = Arc::new(Mutex::new(Box::new(basic_symbol_resolver::Resolver { + let resolver = Arc::new(Box::new(basic_symbol_resolver::Resolver { class_names: Default::default(), id_to_type, id_to_def, - }) as Box)); + }) as Box); for (_, (id, ast, signature)) in functions.into_iter() { if let TopLevelDef::Function { @@ -253,7 +253,7 @@ fn main() { let instance = { let defs = top_level.definitions.read(); - let mut instance = defs[resolver.lock().get_identifier_def("run").unwrap().0].write(); + let mut instance = defs[resolver.get_identifier_def("run").unwrap().0].write(); if let TopLevelDef::Function { instance_to_stmt, instance_to_symbol,