forked from M-Labs/nac3
add RefCell to FunSignature in TypeEnum
This commit is contained in:
parent
d8c3c063ec
commit
3734663188
@ -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<Type, String> {
|
||||
if let Self::Function { signature, .. } = self {
|
||||
Ok(*signature)
|
||||
} else {
|
||||
Err("only expect function def here".into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TopLevelContext {
|
||||
pub definitions: Arc<RwLock<Vec<RwLock<TopLevelDef>>>>,
|
||||
pub unifiers: Arc<RwLock<Vec<(SharedUnifier, PrimitiveStore)>>>,
|
||||
@ -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(())
|
||||
|
@ -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 {
|
||||
|
@ -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()))),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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<Vec<CallId>>),
|
||||
TFunc(FunSignature),
|
||||
TFunc(RefCell<FunSignature>),
|
||||
}
|
||||
|
||||
impl TypeEnum {
|
||||
@ -472,7 +472,7 @@ impl Unifier {
|
||||
}
|
||||
(TCall(calls), TFunc(signature)) => {
|
||||
self.occur_check(a, b)?;
|
||||
let required: Vec<String> = signature
|
||||
let required: Vec<String> = 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)?;
|
||||
}
|
||||
|
@ -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)]
|
||||
|
Loading…
Reference in New Issue
Block a user