lust/bytecode/compiler/
mod.rs

1pub(super) use super::{Chunk, Function, Instruction, Register, Value};
2pub(super) use crate::ast::{
3    BinaryOp, ExprKind, ExternItem, Item, ItemKind, Literal, Stmt, StmtKind, UnaryOp,
4};
5use crate::config::LustConfig;
6pub(super) use crate::number::LustInt;
7pub(super) use crate::{Expr, LustError, Result};
8pub(super) use alloc::{format, string::{String, ToString}, vec, vec::Vec};
9pub(super) use hashbrown::{HashMap, HashSet};
10mod closures;
11mod expressions;
12mod methods;
13mod module;
14mod patterns;
15mod registers;
16mod statements;
17pub struct Compiler {
18    pub(super) functions: Vec<Function>,
19    pub(super) function_table: HashMap<String, usize>,
20    pub(super) trait_impls: Vec<(String, String)>,
21    pub(super) trait_names: HashSet<String>,
22    pub(super) current_function: usize,
23    pub(super) scopes: Vec<Scope>,
24    pub(super) loop_contexts: Vec<LoopContext>,
25    pub(super) next_register: Register,
26    pub(super) max_register: Register,
27    pub(super) current_line: usize,
28    pub(super) imports_by_module: HashMap<String, crate::modules::ModuleImports>,
29    pub(super) current_module: Option<String>,
30    pub(super) entry_module: Option<String>,
31    pub(super) module_locals: HashMap<String, HashSet<String>>,
32    pub(super) current_function_name: Option<String>,
33    pub(super) extern_function_aliases: HashMap<String, String>,
34    pub(super) stdlib_symbols: HashSet<String>,
35}
36
37#[derive(Debug, Clone)]
38pub(super) struct Scope {
39    pub(super) locals: HashMap<String, (Register, bool)>,
40    pub(super) depth: usize,
41}
42
43#[derive(Debug, Clone)]
44pub(super) struct LoopContext {
45    pub(super) continue_target: Option<usize>,
46    pub(super) continue_jumps: Vec<usize>,
47    pub(super) break_jumps: Vec<usize>,
48}
49
50impl Compiler {
51    pub fn new() -> Self {
52        let mut compiler = Self {
53            functions: Vec::new(),
54            function_table: HashMap::new(),
55            trait_impls: Vec::new(),
56            trait_names: HashSet::new(),
57            current_function: 0,
58            scopes: Vec::new(),
59            loop_contexts: Vec::new(),
60            next_register: 0,
61            max_register: 0,
62            current_line: 0,
63            imports_by_module: HashMap::new(),
64            current_module: None,
65            entry_module: None,
66            module_locals: HashMap::new(),
67            current_function_name: None,
68            extern_function_aliases: HashMap::new(),
69            stdlib_symbols: HashSet::new(),
70        };
71        compiler.configure_stdlib(&LustConfig::default());
72        compiler
73    }
74
75    pub fn set_imports_by_module(&mut self, map: HashMap<String, crate::modules::ModuleImports>) {
76        self.imports_by_module = map;
77    }
78
79    pub fn set_entry_module(&mut self, module: impl Into<String>) {
80        self.entry_module = Some(module.into());
81    }
82
83    pub fn get_trait_impls(&self) -> &[(String, String)] {
84        &self.trait_impls
85    }
86
87    pub fn configure_stdlib(&mut self, config: &LustConfig) {
88        self.stdlib_symbols.clear();
89        self.stdlib_symbols.extend(
90            ["print", "println", "type", "tostring", "task"]
91                .into_iter()
92                .map(String::from),
93        );
94        for module in config.enabled_modules() {
95            match module {
96                "io" | "os" => {
97                    self.stdlib_symbols.insert(module.to_string());
98                }
99
100                _ => {}
101            }
102        }
103    }
104
105    pub(super) fn is_stdlib_symbol(&self, name: &str) -> bool {
106        self.stdlib_symbols.contains(name)
107    }
108
109    pub(super) fn record_extern_function(&mut self, name: &str) {
110        let runtime_name = name.to_string();
111        self.extern_function_aliases
112            .entry(runtime_name.clone())
113            .or_insert(runtime_name.clone());
114        let module_name = self
115            .current_module
116            .clone()
117            .or_else(|| self.entry_module.clone());
118        if let Some(module) = module_name {
119            if !name.contains('.') {
120                let qualified = format!("{}.{}", module, name);
121                self.extern_function_aliases
122                    .entry(qualified)
123                    .or_insert(runtime_name);
124            }
125        }
126    }
127
128    pub(super) fn describe_expr_kind(kind: &ExprKind) -> &'static str {
129        match kind {
130            ExprKind::Literal(_) => "literal expression",
131            ExprKind::Identifier(_) => "identifier expression",
132            ExprKind::Binary { .. } => "binary expression",
133            ExprKind::Unary { .. } => "unary expression",
134            ExprKind::Call { .. } => "function call",
135            ExprKind::MethodCall { .. } => "method call",
136            ExprKind::FieldAccess { .. } => "field access",
137            ExprKind::Index { .. } => "index access",
138            ExprKind::Array(_) => "array literal",
139            ExprKind::Map(_) => "map literal",
140            ExprKind::Tuple(_) => "tuple literal",
141            ExprKind::StructLiteral { .. } => "struct literal",
142            ExprKind::EnumConstructor { .. } => "enum constructor",
143            ExprKind::Lambda { .. } => "lambda expression",
144            ExprKind::Paren(_) => "parenthesized expression",
145            ExprKind::Cast { .. } => "cast expression",
146            ExprKind::TypeCheck { .. } => "`is` type check",
147            ExprKind::IsPattern { .. } => "`is` pattern expression",
148            ExprKind::If { .. } => "`if` expression",
149            ExprKind::Block(_) => "block expression",
150            ExprKind::Return(_) => "return expression",
151            ExprKind::Range { .. } => "range expression",
152        }
153    }
154
155    pub(super) fn type_to_string(type_kind: &crate::ast::TypeKind) -> String {
156        use crate::ast::TypeKind;
157        match type_kind {
158            TypeKind::Int => "int".to_string(),
159            TypeKind::Float => "float".to_string(),
160            TypeKind::String => "string".to_string(),
161            TypeKind::Bool => "bool".to_string(),
162            TypeKind::Named(name) => name.clone(),
163            TypeKind::Array(inner) => format!("Array<{}>", Self::type_to_string(&inner.kind)),
164            TypeKind::Map(key, val) => format!(
165                "Map<{}, {}>",
166                Self::type_to_string(&key.kind),
167                Self::type_to_string(&val.kind)
168            ),
169            TypeKind::Table => "Table".to_string(),
170            TypeKind::Option(inner) => format!("Option<{}>", Self::type_to_string(&inner.kind)),
171            TypeKind::Result(ok, err) => format!(
172                "Result<{}, {}>",
173                Self::type_to_string(&ok.kind),
174                Self::type_to_string(&err.kind)
175            ),
176            TypeKind::Function {
177                params,
178                return_type,
179            } => {
180                let param_strs: Vec<String> = params
181                    .iter()
182                    .map(|p| Self::type_to_string(&p.kind))
183                    .collect();
184                format!(
185                    "function({}) -> {}",
186                    param_strs.join(", "),
187                    Self::type_to_string(&return_type.kind)
188                )
189            }
190
191            TypeKind::Tuple(elements) => {
192                let element_strs: Vec<String> = elements
193                    .iter()
194                    .map(|t| Self::type_to_string(&t.kind))
195                    .collect();
196                format!("Tuple<{}>", element_strs.join(", "))
197            }
198
199            TypeKind::Generic(name) => name.clone(),
200            TypeKind::GenericInstance { name, type_args } => {
201                let arg_strs: Vec<String> = type_args
202                    .iter()
203                    .map(|t| Self::type_to_string(&t.kind))
204                    .collect();
205                format!("{}<{}>", name, arg_strs.join(", "))
206            }
207
208            TypeKind::Unknown => "unknown".to_string(),
209            TypeKind::Union(types) => {
210                let type_strs: Vec<String> = types
211                    .iter()
212                    .map(|t| Self::type_to_string(&t.kind))
213                    .collect();
214                format!("{}", type_strs.join(" | "))
215            }
216
217            TypeKind::Unit => "()".to_string(),
218            TypeKind::Infer => "_".to_string(),
219            TypeKind::Ref(inner) => format!("&{}", Self::type_to_string(&inner.kind)),
220            TypeKind::MutRef(inner) => format!("&mut {}", Self::type_to_string(&inner.kind)),
221            TypeKind::Pointer { mutable, pointee } => {
222                if *mutable {
223                    format!("*mut {}", Self::type_to_string(&pointee.kind))
224                } else {
225                    format!("*{}", Self::type_to_string(&pointee.kind))
226                }
227            }
228
229            TypeKind::Trait(name) => name.clone(),
230            TypeKind::TraitBound(traits) => traits.join(" + "),
231        }
232    }
233
234    fn module_context_name(&self) -> Option<&str> {
235        self.current_module
236            .as_deref()
237            .or_else(|| self.entry_module.as_deref())
238    }
239
240    fn is_builtin_type_name(name: &str) -> bool {
241        matches!(
242            name,
243            "int"
244                | "float"
245                | "string"
246                | "bool"
247                | "unknown"
248                | "Table"
249                | "Array"
250                | "Map"
251                | "Option"
252                | "Result"
253                | "Iterator"
254                | "Task"
255                | "TaskStatus"
256                | "TaskInfo"
257        )
258    }
259
260    pub(super) fn resolve_type_name(&self, name: &str) -> String {
261        if let Some((head, tail)) = name.split_once('.') {
262            if let Some(module) = self.module_context_name() {
263                if let Some(imports) = self.imports_by_module.get(module) {
264                    if let Some(real_module) = imports.module_aliases.get(head) {
265                        if tail.is_empty() {
266                            return real_module.clone();
267                        } else {
268                            return format!("{}.{}", real_module, tail);
269                        }
270                    }
271                }
272            }
273
274            return name.to_string();
275        }
276
277        if Self::is_builtin_type_name(name) {
278            return name.to_string();
279        }
280
281        if let Some(module) = self.module_context_name() {
282            if let Some(imports) = self.imports_by_module.get(module) {
283                if let Some(fq) = imports.type_aliases.get(name) {
284                    return fq.clone();
285                }
286            }
287
288            return format!("{}.{}", module, name);
289        }
290
291        name.to_string()
292    }
293}
294
295impl Default for Compiler {
296    fn default() -> Self {
297        Self::new()
298    }
299}