rue_compiler/compile/binding/
list_binding.rs1use 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}