rue_compiler/compile/ty/
lambda.rs1use indexmap::IndexMap;
2use log::debug;
3use rue_ast::{AstLambdaType, AstNode};
4use rue_diagnostic::DiagnosticKind;
5use rue_types::{FunctionType, Type, TypeId};
6
7use crate::{Compiler, compile_generic_parameters, compile_type};
8
9pub fn compile_lambda_type(ctx: &mut Compiler, lambda: &AstLambdaType) -> TypeId {
10 let scope = ctx.alloc_child_scope();
11
12 if let Some(generic_parameters) = lambda.generic_parameters() {
13 compile_generic_parameters(ctx, scope, &generic_parameters);
14 }
15
16 let range = lambda.syntax().text_range();
17 ctx.push_scope(scope, range.start());
18
19 let mut params = IndexMap::new();
20 let mut nil_terminated = true;
21
22 let len = lambda.parameters().count();
23
24 for (i, param) in lambda.parameters().enumerate() {
25 let is_spread = if let Some(spread) = param.spread() {
26 if i == len - 1 {
27 true
28 } else {
29 ctx.diagnostic(&spread, DiagnosticKind::NonFinalSpread);
30 false
31 }
32 } else {
33 false
34 };
35
36 if is_spread {
37 nil_terminated = false;
38 }
39
40 let ty = if let Some(ty) = param.ty() {
41 compile_type(ctx, &ty)
42 } else {
43 debug!("Unresolved lambda parameter type");
44 ctx.builtins().unresolved.ty
45 };
46
47 let name = param
48 .name()
49 .map_or(String::new(), |name| name.text().to_string());
50 params.insert(name, ty);
51 }
52
53 let ret = if let Some(ty) = lambda.return_type() {
54 compile_type(ctx, &ty)
55 } else {
56 debug!("Unresolved lambda return type");
57 ctx.builtins().unresolved.ty
58 };
59
60 ctx.pop_scope(range.end());
61
62 ctx.alloc_type(Type::Function(FunctionType {
63 params,
64 nil_terminated,
65 ret,
66 }))
67}