rue_compiler/compile/binding/
struct_binding.rs

1use log::debug;
2use rue_ast::AstStructBinding;
3use rue_diagnostic::DiagnosticKind;
4use rue_hir::{BindingSymbol, Declaration, Hir, Symbol, SymbolId, SymbolPath, Value};
5
6use crate::{
7    Compiler, Field, FieldResult, compile_field, create_binding, create_binding_for_identifier,
8};
9
10pub fn create_struct_binding(
11    ctx: &mut Compiler,
12    symbol: SymbolId,
13    struct_binding: &AstStructBinding,
14) {
15    let ty = ctx.symbol_type(symbol);
16    let reference = Value::new(ctx.alloc_hir(Hir::Reference(symbol)), ty)
17        .with_reference(SymbolPath::new(symbol, vec![]));
18
19    for field in struct_binding.fields() {
20        let Some(name) = field.name() else {
21            continue;
22        };
23
24        let value = match compile_field(ctx, reference.clone(), &Field::Named(name.text())) {
25            FieldResult::Value(value) => value,
26            FieldResult::Unknown => {
27                debug!("Unresolved field access due to unknown field");
28                let type_name = ctx.type_name(reference.ty);
29                ctx.diagnostic(
30                    &name,
31                    DiagnosticKind::UnknownField(name.text().to_string(), type_name),
32                );
33                ctx.builtins().unresolved.clone()
34            }
35            FieldResult::Error => {
36                debug!("Unresolved field access due to missing field in underlying struct type");
37                let type_name = ctx.type_name(reference.ty);
38                ctx.diagnostic(
39                    &name,
40                    DiagnosticKind::MissingField(name.text().to_string(), type_name),
41                );
42                ctx.builtins().unresolved.clone()
43            }
44        };
45
46        let binding_symbol = ctx.alloc_symbol(Symbol::Binding(BindingSymbol {
47            name: None,
48            value,
49            inline: true,
50        }));
51        ctx.push_declaration(Declaration::Symbol(binding_symbol));
52        ctx.reference(Declaration::Symbol(symbol));
53
54        if let Some(binding) = field.binding() {
55            create_binding(ctx, binding_symbol, &binding);
56        } else {
57            create_binding_for_identifier(ctx, binding_symbol, name);
58        }
59
60        ctx.pop_declaration();
61    }
62}