use log::debug;
use rue_ast::{AstListBinding, AstNode};
use rue_diagnostic::DiagnosticKind;
use rue_hir::{BindingSymbol, Declaration, Hir, Symbol, SymbolId, SymbolPath, Value};
use crate::{Compiler, compile_pair_fields, create_binding};
pub fn create_list_binding(ctx: &mut Compiler, symbol: SymbolId, list_binding: &AstListBinding) {
let ty = ctx.symbol_type(symbol);
let mut symbol = symbol;
let mut reference = Value::new(ctx.alloc_hir(Hir::Reference(symbol)), ty)
.with_reference(SymbolPath::new(symbol, vec![]));
let mut needs_popping = 0;
let len = list_binding.items().count();
for (i, item) in list_binding.items().enumerate() {
let mut is_cons = true;
if let Some(spread) = item.spread() {
if i == len - 1 {
is_cons = false;
} else {
ctx.diagnostic(&spread, DiagnosticKind::InvalidSpread);
}
}
let Some(binding) = item.binding() else {
debug!("Unresolved list item binding");
continue;
};
if !is_cons {
create_binding(ctx, symbol, &binding);
continue;
}
let (first_value, rest_value) = compile_pair_fields(ctx, binding.syntax(), &reference);
let first_symbol = ctx.alloc_symbol(Symbol::Binding(BindingSymbol {
name: None,
value: first_value,
inline: true,
}));
ctx.push_declaration(Declaration::Symbol(first_symbol));
ctx.reference(Declaration::Symbol(symbol), None);
create_binding(ctx, first_symbol, &binding);
ctx.pop_declaration();
let rest_symbol = ctx.alloc_symbol(Symbol::Binding(BindingSymbol {
name: None,
value: rest_value.clone(),
inline: true,
}));
needs_popping += 1;
ctx.push_declaration(Declaration::Symbol(rest_symbol));
ctx.reference(Declaration::Symbol(symbol), None);
symbol = rest_symbol;
reference = rest_value;
}
for _ in 0..needs_popping {
ctx.pop_declaration();
}
}