rue_compiler/compile/expr/
literal.rs

1use std::{borrow::Cow, str::FromStr};
2
3use log::debug;
4use num_bigint::BigInt;
5use rue_ast::AstLiteralExpr;
6use rue_hir::{Hir, Value};
7use rue_lir::bigint_atom;
8use rue_parser::{SyntaxKind, T};
9use rue_types::{Atom, AtomRestriction, AtomSemantic, Type};
10
11use crate::Compiler;
12
13pub fn compile_literal_expr(ctx: &mut Compiler, expr: &AstLiteralExpr) -> Value {
14    let Some(value) = expr.value() else {
15        debug!("Unresolved literal expr");
16        return ctx.builtins().unresolved.clone();
17    };
18
19    match value.kind() {
20        SyntaxKind::String => {
21            let mut text = value.text();
22
23            if let Some(stripped) = text.strip_prefix('"') {
24                text = stripped;
25            }
26
27            if let Some(stripped) = text.strip_suffix('"') {
28                text = stripped;
29            }
30
31            let hir = ctx.alloc_hir(Hir::String(text.to_string()));
32            let ty = ctx.alloc_type(Type::Atom(Atom::new(
33                AtomSemantic::Bytes,
34                Some(AtomRestriction::Value(Cow::Owned(text.as_bytes().to_vec()))),
35            )));
36            Value::new(hir, ty)
37        }
38        SyntaxKind::Hex => {
39            let mut text = value.text();
40
41            if let Some(stripped) = text.strip_prefix("0x") {
42                text = stripped;
43            }
44
45            let mut text = text.replace('_', "");
46
47            if text.len() % 2 == 1 {
48                text.insert(0, '0');
49            }
50
51            let bytes = hex::decode(text).unwrap();
52            let ty = ctx.alloc_type(Type::Atom(if bytes.is_empty() {
53                Atom::NIL
54            } else {
55                Atom::new(
56                    if bytes.len() == 48 {
57                        AtomSemantic::PublicKey
58                    } else if bytes.len() == 96 {
59                        AtomSemantic::Signature
60                    } else {
61                        AtomSemantic::Bytes
62                    },
63                    Some(AtomRestriction::Value(Cow::Owned(bytes.clone()))),
64                )
65            }));
66
67            Value::new(ctx.alloc_hir(Hir::Bytes(bytes)), ty)
68        }
69        SyntaxKind::Integer => {
70            let text = value.text().replace('_', "");
71
72            let num = BigInt::from_str(&text).unwrap();
73            let ty = ctx.alloc_type(Type::Atom(Atom::new(
74                AtomSemantic::Int,
75                Some(AtomRestriction::Value(Cow::Owned(bigint_atom(num.clone())))),
76            )));
77
78            Value::new(ctx.alloc_hir(Hir::Int(num)), ty)
79        }
80        T![nil] => ctx.builtins().nil.clone(),
81        T![true] => ctx.builtins().true_value.clone(),
82        T![false] => ctx.builtins().false_value.clone(),
83        _ => unreachable!(),
84    }
85}