rue_compiler/compile/ty/
lambda.rs

1use 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}