rue_compiler/compile/item/
constant.rs

1use log::debug;
2use rue_ast::{AstConstantItem, AstNode};
3use rue_diagnostic::DiagnosticKind;
4use rue_hir::{ConstantSymbol, Declaration, Symbol, SymbolId, Value};
5
6use crate::{Compiler, CompletionContext, SyntaxItemKind, compile_expr, compile_type};
7
8pub fn declare_constant(ctx: &mut Compiler, constant: &AstConstantItem) -> SymbolId {
9    ctx.add_syntax(
10        SyntaxItemKind::CompletionContext(CompletionContext::Item),
11        constant.syntax().text_range(),
12    );
13
14    let symbol = ctx.alloc_symbol(Symbol::Unresolved);
15
16    ctx.push_declaration(Declaration::Symbol(symbol));
17
18    let ty = if let Some(ty) = constant.ty() {
19        compile_type(ctx, &ty)
20    } else {
21        debug!("Unresolved constant type");
22        ctx.builtins().unresolved.ty
23    };
24
25    let value = ctx.builtins().unresolved.hir;
26
27    let name = constant.name().map(|name| ctx.local_name(&name));
28
29    *ctx.symbol_mut(symbol) = Symbol::Constant(ConstantSymbol {
30        name,
31        value: Value::new(value, ty),
32        inline: constant.inline().is_some(),
33    });
34
35    if let Some(name) = constant.name() {
36        if ctx.last_scope().symbol(name.text()).is_some() {
37            ctx.diagnostic(
38                &name,
39                DiagnosticKind::DuplicateSymbol(name.text().to_string()),
40            );
41        } else {
42            ctx.last_scope_mut().insert_symbol(
43                name.text().to_string(),
44                symbol,
45                constant.export().is_some(),
46            );
47        }
48
49        ctx.declaration_span(Declaration::Symbol(symbol), name.text_range());
50    }
51
52    ctx.pop_declaration();
53
54    symbol
55}
56
57pub fn compile_constant(ctx: &mut Compiler, constant: &AstConstantItem, symbol: SymbolId) {
58    ctx.push_declaration(Declaration::Symbol(symbol));
59
60    let ty = if let Symbol::Constant(ConstantSymbol { value, .. }) = ctx.symbol(symbol) {
61        value.ty
62    } else {
63        unreachable!();
64    };
65
66    let resolved_value = if let Some(expr) = constant.value() {
67        let value = compile_expr(ctx, &expr, Some(ty));
68        ctx.assign_type(expr.syntax(), value.ty, ty);
69        value
70    } else {
71        debug!("Unresolved constant value");
72        ctx.builtins().unresolved.clone()
73    };
74
75    let Symbol::Constant(ConstantSymbol { value, .. }) = ctx.symbol_mut(symbol) else {
76        unreachable!();
77    };
78
79    *value = resolved_value.with_type(ty);
80
81    ctx.pop_declaration();
82}