rue_compiler/compile/binding/
list_binding.rs

1use log::debug;
2use rue_ast::{AstListBinding, AstNode};
3use rue_diagnostic::DiagnosticKind;
4use rue_hir::{BindingSymbol, Declaration, Hir, Symbol, SymbolId, SymbolPath, Value};
5
6use crate::{Compiler, compile_pair_fields, create_binding};
7
8pub fn create_list_binding(ctx: &mut Compiler, symbol: SymbolId, list_binding: &AstListBinding) {
9    let ty = ctx.symbol_type(symbol);
10
11    let mut symbol = symbol;
12    let mut reference = Value::new(ctx.alloc_hir(Hir::Reference(symbol)), ty)
13        .with_reference(SymbolPath::new(symbol, vec![]));
14    let mut needs_popping = 0;
15
16    let len = list_binding.items().count();
17
18    for (i, item) in list_binding.items().enumerate() {
19        let mut is_cons = true;
20
21        if let Some(spread) = item.spread() {
22            if i == len - 1 {
23                is_cons = false;
24            } else {
25                ctx.diagnostic(&spread, DiagnosticKind::InvalidSpread);
26            }
27        }
28
29        let Some(binding) = item.binding() else {
30            debug!("Unresolved list item binding");
31            continue;
32        };
33
34        if !is_cons {
35            create_binding(ctx, symbol, &binding);
36            continue;
37        }
38
39        let (first_value, rest_value) = compile_pair_fields(ctx, binding.syntax(), &reference);
40
41        let first_symbol = ctx.alloc_symbol(Symbol::Binding(BindingSymbol {
42            name: None,
43            value: first_value,
44            inline: true,
45        }));
46        ctx.push_declaration(Declaration::Symbol(first_symbol));
47        ctx.reference(Declaration::Symbol(symbol));
48        create_binding(ctx, first_symbol, &binding);
49        ctx.pop_declaration();
50
51        let rest_symbol = ctx.alloc_symbol(Symbol::Binding(BindingSymbol {
52            name: None,
53            value: rest_value.clone(),
54            inline: true,
55        }));
56
57        needs_popping += 1;
58        ctx.push_declaration(Declaration::Symbol(rest_symbol));
59        ctx.reference(Declaration::Symbol(symbol));
60
61        symbol = rest_symbol;
62        reference = rest_value;
63    }
64
65    for _ in 0..needs_popping {
66        ctx.pop_declaration();
67    }
68}