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