rue_compiler/compile/expr/
literal.rs1use 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}