diff --git a/nac3core/src/top_level.rs b/nac3core/src/top_level.rs index ed1b24f48..afec33fee 100644 --- a/nac3core/src/top_level.rs +++ b/nac3core/src/top_level.rs @@ -1,6 +1,5 @@ -use std::borrow::{Borrow, BorrowMut}; -use std::collections::HashSet; -use std::{collections::HashMap, sync::Arc}; +use std::borrow::BorrowMut; +use std::{collections::HashMap, collections::HashSet, sync::Arc}; use super::typecheck::type_inferencer::PrimitiveStore; use super::typecheck::typedef::{SharedUnifier, Type, TypeEnum, Unifier}; @@ -52,6 +51,16 @@ pub enum TopLevelDef { }, } +impl TopLevelDef { + fn get_function_type(&self) -> Result { + if let Self::Function { signature, .. } = self { + Ok(*signature) + } else { + Err("only expect function def here".into()) + } + } +} + pub struct TopLevelContext { pub definitions: Arc>>>, pub unifiers: Arc>>, @@ -219,18 +228,15 @@ impl TopLevelComposer { let fun_name = Self::name_mangling(class_name.clone(), name); let def_id = def_list.len(); - // add to unifier - let ty = self.unifier.write().add_ty(TypeEnum::TFunc(FunSignature { - args: Default::default(), - ret: self.primitives.none, - vars: Default::default(), - })); - // add to the definition list def_list.push( Self::make_top_level_function_def( fun_name.clone(), - ty, + self.unifier.write().add_ty(TypeEnum::TFunc(FunSignature { + args: Default::default(), + ret: self.primitives.none.into(), + vars: Default::default(), + }.into())), resolver.clone(), ) .into(), @@ -309,7 +315,7 @@ impl TopLevelComposer { } else { continue } }; - let mut generic_occured = false; + let mut is_generic = false; for b in class_bases { match &b.node { // analyze typevars bounded to the class, @@ -321,8 +327,8 @@ impl TopLevelComposer { // can only be `Generic[...]` and this can only appear once if let ast::ExprKind::Name { id, .. } = &value.node { if id == "Generic" { - if !generic_occured { - generic_occured = true; + if !is_generic { + is_generic = true; true } else { return Err("Only single Generic[...] can be in bases".into()) @@ -467,10 +473,10 @@ impl TopLevelComposer { while !to_be_analyzed_class.is_empty() { let ind = to_be_analyzed_class.remove(0).0; - let (class_def, class_ast) = ( &mut def_list[ind], &ast_list[ind] ); + let ( class_name, class_fields, @@ -491,7 +497,10 @@ impl TopLevelComposer { }, .. }) = class_ast { (name, fields, methods, resolver, body) } else { unreachable!("must be both class") } - } else { continue } + } else { + to_be_analyzed_class.push(DefinitionId(ind)); + continue + } }; for b in class_body { if let ast::StmtKind::FunctionDef { @@ -508,13 +517,19 @@ impl TopLevelComposer { class_name.into(), func_name) ).unwrap(); - - let a = &def_list[method_def_id.0]; + let method_def = def_list[method_def_id.0].write(); + let method_ty = method_def.get_function_type()?; + let method_signature = unifier.get_ty(method_ty); + + if let TypeEnum::TFunc(sig) = method_signature.as_ref() { + let mut sig = &mut *sig.borrow_mut(); + } else { unreachable!() } + + } else { // what should we do with `class A: a = 3`? continue } - } } Ok(()) diff --git a/nac3core/src/typecheck/magic_methods.rs b/nac3core/src/typecheck/magic_methods.rs index 29615aa27..d7eb0dbe9 100644 --- a/nac3core/src/typecheck/magic_methods.rs +++ b/nac3core/src/typecheck/magic_methods.rs @@ -84,7 +84,7 @@ pub fn impl_binop( ret: ret_ty, vars: HashMap::new(), args: vec![FuncArg { ty: other, default_value: None, name: "other".into() }], - })) + }.into())) }); fields.borrow_mut().insert(binop_assign_name(op).into(), { @@ -97,7 +97,7 @@ pub fn impl_binop( ret: ret_ty, vars: HashMap::new(), args: vec![FuncArg { ty: other, default_value: None, name: "other".into() }], - })) + }.into())) }); } } else { @@ -120,7 +120,7 @@ pub fn impl_unaryop( ret: ret_ty, vars: HashMap::new(), args: vec![], - })), + }.into())), ); } } else { @@ -143,7 +143,7 @@ pub fn impl_cmpop( ret: store.bool, vars: HashMap::new(), args: vec![FuncArg { ty: other_ty, default_value: None, name: "other".into() }], - })), + }.into())), ); } } else { diff --git a/nac3core/src/typecheck/type_inferencer/mod.rs b/nac3core/src/typecheck/type_inferencer/mod.rs index 304431f38..72c47f60c 100644 --- a/nac3core/src/typecheck/type_inferencer/mod.rs +++ b/nac3core/src/typecheck/type_inferencer/mod.rs @@ -258,7 +258,7 @@ impl<'a> Inferencer<'a> { Ok(Located { location, node: ExprKind::Lambda { args: args.into(), body: body.into() }, - custom: Some(self.unifier.add_ty(TypeEnum::TFunc(fun))), + custom: Some(self.unifier.add_ty(TypeEnum::TFunc(fun.into()))), }) } diff --git a/nac3core/src/typecheck/type_inferencer/test.rs b/nac3core/src/typecheck/type_inferencer/test.rs index e85269ea0..29eafdb47 100644 --- a/nac3core/src/typecheck/type_inferencer/test.rs +++ b/nac3core/src/typecheck/type_inferencer/test.rs @@ -180,14 +180,14 @@ impl TestEnvironment { args: vec![], ret: foo_ty, vars: [(id, v0)].iter().cloned().collect(), - })), + }.into())), ); let fun = unifier.add_ty(TypeEnum::TFunc(FunSignature { args: vec![], ret: int32, vars: Default::default(), - })); + }.into())); let bar = unifier.add_ty(TypeEnum::TObj { obj_id: DefinitionId(6), fields: [("a".into(), int32), ("b".into(), fun)] @@ -211,7 +211,7 @@ impl TestEnvironment { args: vec![], ret: bar, vars: Default::default(), - })), + }.into())), ); let bar2 = unifier.add_ty(TypeEnum::TObj { @@ -237,7 +237,7 @@ impl TestEnvironment { args: vec![], ret: bar2, vars: Default::default(), - })), + }.into())), ); let class_names = [("Bar".into(), bar), ("Bar2".into(), bar2)].iter().cloned().collect(); diff --git a/nac3core/src/typecheck/typedef/mod.rs b/nac3core/src/typecheck/typedef/mod.rs index 6f0c34d7c..05b2336bc 100644 --- a/nac3core/src/typecheck/typedef/mod.rs +++ b/nac3core/src/typecheck/typedef/mod.rs @@ -1,5 +1,5 @@ use itertools::{chain, zip, Itertools}; -use std::borrow::Cow; +use std::borrow::{Borrow, Cow}; use std::cell::RefCell; use std::collections::HashMap; use std::iter::once; @@ -77,7 +77,7 @@ pub enum TypeEnum { ty: Type, }, TCall(RefCell>), - TFunc(FunSignature), + TFunc(RefCell), } impl TypeEnum { @@ -472,7 +472,7 @@ impl Unifier { } (TCall(calls), TFunc(signature)) => { self.occur_check(a, b)?; - let required: Vec = signature + let required: Vec = signature.borrow() .args .iter() .filter(|v| v.default_value.is_none()) @@ -482,7 +482,7 @@ impl Unifier { // we unify every calls to the function signature. for c in calls.borrow().iter() { let Call { posargs, kwargs, ret, fun } = &*self.calls[c.0].clone(); - let instantiated = self.instantiate_fun(b, signature); + let instantiated = self.instantiate_fun(b, &*signature.borrow()); let r = self.get_ty(instantiated); let r = r.as_ref(); let signature; @@ -495,9 +495,9 @@ impl Unifier { // arguments) are provided, and do not provide the same argument twice. let mut required = required.clone(); let mut all_names: Vec<_> = - signature.args.iter().map(|v| (v.name.clone(), v.ty)).rev().collect(); + signature.borrow().args.iter().map(|v| (v.name.clone(), v.ty)).rev().collect(); for (i, t) in posargs.iter().enumerate() { - if signature.args.len() <= i { + if signature.borrow().args.len() <= i { return Err("Too many arguments.".to_string()); } if !required.is_empty() { @@ -518,12 +518,13 @@ impl Unifier { if !required.is_empty() { return Err("Expected more arguments".to_string()); } - self.unify(*ret, signature.ret)?; + self.unify(*ret, signature.borrow().ret)?; *fun.borrow_mut() = Some(instantiated); } self.set_a_to_b(a, b); } (TFunc(sign1), TFunc(sign2)) => { + let (sign1, sign2) = (&*sign1.borrow(), &*sign2.borrow()); if !sign1.vars.is_empty() || !sign2.vars.is_empty() { return Err("Polymorphic function pointer is prohibited.".to_string()); } @@ -604,13 +605,14 @@ impl Unifier { TypeEnum::TCall { .. } => "call".to_owned(), TypeEnum::TFunc(signature) => { let params = signature + .borrow() .args .iter() .map(|arg| { format!("{}={}", arg.name, self.stringify(arg.ty, obj_to_name, var_to_name)) }) .join(", "); - let ret = self.stringify(signature.ret, obj_to_name, var_to_name); + let ret = self.stringify(signature.borrow().ret, obj_to_name, var_to_name); format!("fn[[{}], {}]", params, ret) } } @@ -723,7 +725,8 @@ impl Unifier { None } } - TypeEnum::TFunc(FunSignature { args, ret, vars: params }) => { + TypeEnum::TFunc(sig) => { + let FunSignature { args, ret, vars: params } = &*sig.borrow(); let new_params = self.subst_map(params, mapping); let new_ret = self.subst(*ret, mapping); let mut new_args = Cow::from(args); @@ -738,7 +741,7 @@ impl Unifier { let params = new_params.unwrap_or_else(|| params.clone()); let ret = new_ret.unwrap_or_else(|| *ret); let args = new_args.into_owned(); - Some(self.add_ty(TypeEnum::TFunc(FunSignature { args, ret, vars: params }))) + Some(self.add_ty(TypeEnum::TFunc(FunSignature { args, ret, vars: params }.into()))) } else { None } @@ -809,7 +812,8 @@ impl Unifier { self.occur_check(a, *t)?; } } - TypeEnum::TFunc(FunSignature { args, ret, vars: params }) => { + TypeEnum::TFunc(sig) => { + let FunSignature { args, ret, vars: params } = &*sig.borrow(); for t in chain!(args.iter().map(|v| &v.ty), params.values(), once(ret)) { self.occur_check(a, *t)?; } diff --git a/nac3core/src/typecheck/typedef/test.rs b/nac3core/src/typecheck/typedef/test.rs index d782c14fa..3aaa78918 100644 --- a/nac3core/src/typecheck/typedef/test.rs +++ b/nac3core/src/typecheck/typedef/test.rs @@ -333,7 +333,7 @@ fn test_virtual() { args: vec![], ret: int, vars: HashMap::new(), - })); + }.into())); let bar = env.unifier.add_ty(TypeEnum::TObj { obj_id: DefinitionId(5), fields: [("f".to_string(), fun), ("a".to_string(), int)]