optimization (#13) #15
@ -248,17 +248,25 @@ impl<'a> Inferencer<'a> {
|
|||||||
if let TypeEnum::TFunc(sign) = &*self.unifier.get_ty(*ty) {
|
if let TypeEnum::TFunc(sign) = &*self.unifier.get_ty(*ty) {
|
||||||
let sign = sign.borrow();
|
let sign = sign.borrow();
|
||||||
if sign.vars.is_empty() {
|
if sign.vars.is_empty() {
|
||||||
let call = self.unifier.add_call(Call {
|
let call = Call {
|
||||||
posargs: params,
|
posargs: params,
|
||||||
kwargs: HashMap::new(),
|
kwargs: HashMap::new(),
|
||||||
ret: sign.ret,
|
ret: sign.ret,
|
||||||
fun: RefCell::new(None),
|
fun: RefCell::new(None),
|
||||||
});
|
};
|
||||||
let call = self.unifier.add_ty(TypeEnum::TCall(vec![call].into()));
|
|
||||||
if let Some(ret) = ret {
|
if let Some(ret) = ret {
|
||||||
self.unifier.unify(sign.ret, ret).unwrap();
|
self.unifier.unify(sign.ret, ret).unwrap();
|
||||||
}
|
}
|
||||||
self.constrain(call, *ty, &location)?;
|
let required: Vec<_> = sign
|
||||||
|
.args
|
||||||
|
.iter()
|
||||||
|
.filter(|v| v.default_value.is_none())
|
||||||
|
.map(|v| v.name)
|
||||||
|
.rev()
|
||||||
|
.collect();
|
||||||
|
self.unifier
|
||||||
|
.unify_call(&call, *ty, &sign, &required)
|
||||||
|
.map_err(|old| format!("{} at {}", old, location))?;
|
||||||
return Ok(sign.ret);
|
return Ok(sign.ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -491,7 +499,7 @@ impl<'a> Inferencer<'a> {
|
|||||||
if let TypeEnum::TFunc(sign) = &*self.unifier.get_ty(func.custom.unwrap()) {
|
if let TypeEnum::TFunc(sign) = &*self.unifier.get_ty(func.custom.unwrap()) {
|
||||||
let sign = sign.borrow();
|
let sign = sign.borrow();
|
||||||
if sign.vars.is_empty() {
|
if sign.vars.is_empty() {
|
||||||
let call = self.unifier.add_call(Call {
|
let call = Call {
|
||||||
posargs: args.iter().map(|v| v.custom.unwrap()).collect(),
|
posargs: args.iter().map(|v| v.custom.unwrap()).collect(),
|
||||||
kwargs: keywords
|
kwargs: keywords
|
||||||
.iter()
|
.iter()
|
||||||
@ -499,9 +507,17 @@ impl<'a> Inferencer<'a> {
|
|||||||
.collect(),
|
.collect(),
|
||||||
fun: RefCell::new(None),
|
fun: RefCell::new(None),
|
||||||
ret: sign.ret,
|
ret: sign.ret,
|
||||||
});
|
};
|
||||||
let call = self.unifier.add_ty(TypeEnum::TCall(vec![call].into()));
|
let required: Vec<_> = sign
|
||||||
self.unify(func.custom.unwrap(), call, &func.location)?;
|
.args
|
||||||
|
.iter()
|
||||||
|
.filter(|v| v.default_value.is_none())
|
||||||
|
.map(|v| v.name)
|
||||||
|
.rev()
|
||||||
|
.collect();
|
||||||
|
self.unifier
|
||||||
|
.unify_call(&call, func.custom.unwrap(), &sign, &required)
|
||||||
|
.map_err(|old| format!("{} at {}", old, location))?;
|
||||||
return Ok(Located {
|
return Ok(Located {
|
||||||
location,
|
location,
|
||||||
custom: Some(sign.ret),
|
custom: Some(sign.ret),
|
||||||
|
@ -374,6 +374,54 @@ impl Unifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn unify_call(&mut self, call: &Call, b: Type, signature: &FunSignature, required: &[StrRef]) -> Result<(), String> {
|
||||||
|
let Call { posargs, kwargs, ret, fun } = call;
|
||||||
|
let instantiated = self.instantiate_fun(b, &*signature);
|
||||||
|
let r = self.get_ty(instantiated);
|
||||||
|
let r = r.as_ref();
|
||||||
|
let signature;
|
||||||
|
if let TypeEnum::TFunc(s) = &*r {
|
||||||
|
signature = s;
|
||||||
|
} else {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
// we check to make sure that all required arguments (those without default
|
||||||
|
// arguments) are provided, and do not provide the same argument twice.
|
||||||
|
let mut required = required.to_vec();
|
||||||
|
let mut all_names: Vec<_> = signature
|
||||||
|
.borrow()
|
||||||
|
.args
|
||||||
|
.iter()
|
||||||
|
.map(|v| (v.name, v.ty))
|
||||||
|
.rev()
|
||||||
|
.collect();
|
||||||
|
for (i, t) in posargs.iter().enumerate() {
|
||||||
|
if signature.borrow().args.len() <= i {
|
||||||
|
return Err("Too many arguments.".to_string());
|
||||||
|
}
|
||||||
|
if !required.is_empty() {
|
||||||
|
required.pop();
|
||||||
|
}
|
||||||
|
self.unify(all_names.pop().unwrap().1, *t)?;
|
||||||
|
}
|
||||||
|
for (k, t) in kwargs.iter() {
|
||||||
|
if let Some(i) = required.iter().position(|v| v == k) {
|
||||||
|
required.remove(i);
|
||||||
|
}
|
||||||
|
let i = all_names
|
||||||
|
.iter()
|
||||||
|
.position(|v| &v.0 == k)
|
||||||
|
.ok_or_else(|| format!("Unknown keyword argument {}", k))?;
|
||||||
|
self.unify(all_names.remove(i).1, *t)?;
|
||||||
|
}
|
||||||
|
if !required.is_empty() {
|
||||||
|
return Err("Expected more arguments".to_string());
|
||||||
|
}
|
||||||
|
self.unify(*ret, signature.borrow().ret)?;
|
||||||
|
*fun.borrow_mut() = Some(instantiated);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn unify(&mut self, a: Type, b: Type) -> Result<(), String> {
|
pub fn unify(&mut self, a: Type, b: Type) -> Result<(), String> {
|
||||||
if self.unification_table.unioned(a, b) {
|
if self.unification_table.unioned(a, b) {
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -574,51 +622,10 @@ impl Unifier {
|
|||||||
.rev()
|
.rev()
|
||||||
.collect();
|
.collect();
|
||||||
// we unify every calls to the function signature.
|
// we unify every calls to the function signature.
|
||||||
|
let signature = signature.borrow();
|
||||||
for c in calls.borrow().iter() {
|
for c in calls.borrow().iter() {
|
||||||
let Call { posargs, kwargs, ret, fun } = &*self.calls[c.0].clone();
|
let call = self.calls[c.0].clone();
|
||||||
let instantiated = self.instantiate_fun(b, &*signature.borrow());
|
self.unify_call(&call, b, &signature, &required)?;
|
||||||
let r = self.get_ty(instantiated);
|
|
||||||
let r = r.as_ref();
|
|
||||||
let signature;
|
|
||||||
if let TypeEnum::TFunc(s) = &*r {
|
|
||||||
signature = s;
|
|
||||||
} else {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
// we check to make sure that all required arguments (those without default
|
|
||||||
// arguments) are provided, and do not provide the same argument twice.
|
|
||||||
let mut required = required.clone();
|
|
||||||
let mut all_names: Vec<_> = signature
|
|
||||||
.borrow()
|
|
||||||
.args
|
|
||||||
.iter()
|
|
||||||
.map(|v| (v.name, v.ty))
|
|
||||||
.rev()
|
|
||||||
.collect();
|
|
||||||
for (i, t) in posargs.iter().enumerate() {
|
|
||||||
if signature.borrow().args.len() <= i {
|
|
||||||
return Err("Too many arguments.".to_string());
|
|
||||||
}
|
|
||||||
if !required.is_empty() {
|
|
||||||
required.pop();
|
|
||||||
}
|
|
||||||
self.unify(all_names.pop().unwrap().1, *t)?;
|
|
||||||
}
|
|
||||||
for (k, t) in kwargs.iter() {
|
|
||||||
if let Some(i) = required.iter().position(|v| v == k) {
|
|
||||||
required.remove(i);
|
|
||||||
}
|
|
||||||
let i = all_names
|
|
||||||
.iter()
|
|
||||||
.position(|v| &v.0 == k)
|
|
||||||
.ok_or_else(|| format!("Unknown keyword argument {}", k))?;
|
|
||||||
self.unify(all_names.remove(i).1, *t)?;
|
|
||||||
}
|
|
||||||
if !required.is_empty() {
|
|
||||||
return Err("Expected more arguments".to_string());
|
|
||||||
}
|
|
||||||
self.unify(*ret, signature.borrow().ret)?;
|
|
||||||
*fun.borrow_mut() = Some(instantiated);
|
|
||||||
}
|
}
|
||||||
self.set_a_to_b(a, b);
|
self.set_a_to_b(a, b);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user