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}