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