use indexmap::IndexMap;
use log::debug;
use rue_ast::{AstLambdaType, AstNode};
use rue_diagnostic::DiagnosticKind;
use rue_types::{FunctionType, Type, TypeId};
use crate::{Compiler, compile_generic_parameters, compile_type};
pub fn compile_lambda_type(ctx: &mut Compiler, lambda: &AstLambdaType) -> TypeId {
let scope = ctx.alloc_child_scope();
if let Some(generic_parameters) = lambda.generic_parameters() {
compile_generic_parameters(ctx, scope, &generic_parameters);
}
let range = lambda.syntax().text_range();
ctx.push_scope(scope, range.start());
let mut params = IndexMap::new();
let mut nil_terminated = true;
let len = lambda.parameters().count();
for (i, param) in lambda.parameters().enumerate() {
let is_spread = if let Some(spread) = param.spread() {
if i == len - 1 {
true
} else {
ctx.diagnostic(&spread, DiagnosticKind::NonFinalSpread);
false
}
} else {
false
};
if is_spread {
nil_terminated = false;
}
let ty = if let Some(ty) = param.ty() {
compile_type(ctx, &ty)
} else {
debug!("Unresolved lambda parameter type");
ctx.builtins().unresolved.ty
};
let name = param
.name()
.map_or(String::new(), |name| name.text().to_string());
params.insert(name, ty);
}
let ret = if let Some(ty) = lambda.return_type() {
compile_type(ctx, &ty)
} else {
debug!("Unresolved lambda return type");
ctx.builtins().unresolved.ty
};
ctx.pop_scope(range.end());
ctx.alloc_type(Type::Function(FunctionType {
params,
nil_terminated,
ret,
}))
}