use super::Checker;
use super::members::Signature;
use super::model::Type;
use crate::ast::{Arg, Expr, ExprKind, Param};
impl Checker<'_, '_, '_> {
pub(super) fn constructed(&mut self, e: &Expr, t: &Type, args: &[Arg]) {
let at = e.span;
let sigs = match t {
Type::Own(name, targs) => self.constructors(name, targs),
_ => Vec::new(),
};
let given: Vec<Type> = args
.iter()
.map(|a| match a.value.kind {
ExprKind::Lambda { .. } if !sigs.is_empty() => self.quietly(|c| c.expr(&a.value)),
_ => self.expr(&a.value),
})
.collect();
if !sigs.is_empty() {
let args: Vec<&Arg> = args.iter().collect();
if let (_, Some(chosen)) = self.pick(&sigs, &given, &args, at) {
self.types.set_constructor(e, chosen.index);
if let Type::Own(name, targs) = t {
let key = super::own::TypeKey::new(name, targs.len());
self.crossing_new(&key, chosen.index, &args);
}
if let Some(from) = chosen.rest_from {
let item = match sigs[chosen.index].params.last() {
Some(Type::Array(item, _)) => (**item).clone(),
_ => Type::Unknown,
};
self.types.set_constructor_rest(e, from, item);
}
}
}
}
fn constructors(&mut self, name: &str, targs: &[Type]) -> Vec<Signature> {
let Some(own) = self.own.get(name, targs.len()) else {
return Vec::new();
};
if !own.heap {
return Vec::new();
}
let mut all = own.ctors.clone();
if all.is_empty() || !own.ctor.is_empty() {
all.push(own.ctor.clone());
}
let context = self.context_of(name, targs);
all.iter()
.map(|params| self.in_context(&context, |c| c.ctor_signature(params)))
.collect()
}
fn ctor_signature(&mut self, params: &[Param]) -> Signature {
Signature {
params: params.iter().map(|p| self.type_of(&p.ty)).collect(),
passes: params.iter().map(|p| p.pass).collect(),
required: params
.iter()
.take_while(|p| p.default.is_none() && !p.params)
.count(),
ret: Type::Void,
generics: Vec::new(),
bound: Default::default(),
rest: params.last().is_some_and(|p| p.params),
}
}
}