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}