1use super::*;
2use crate::ast::Type;
3use crate::config::LustConfig;
4use alloc::rc::Rc;
5use alloc::string::String;
6use alloc::vec::Vec;
7use core::result::Result as CoreResult;
8use core::{array, mem};
9
10#[derive(Debug, Clone)]
11pub struct NativeExportParam {
12 name: String,
13 ty: String,
14}
15
16impl NativeExportParam {
17 pub fn new(name: impl Into<String>, ty: impl Into<String>) -> Self {
18 Self {
19 name: name.into(),
20 ty: ty.into(),
21 }
22 }
23
24 pub fn name(&self) -> &str {
25 &self.name
26 }
27
28 pub fn ty(&self) -> &str {
29 &self.ty
30 }
31}
32
33#[derive(Debug, Clone)]
34pub struct NativeExport {
35 name: String,
36 params: Vec<NativeExportParam>,
37 return_type: String,
38 doc: Option<String>,
39}
40
41impl NativeExport {
42 pub fn new(
43 name: impl Into<String>,
44 params: Vec<NativeExportParam>,
45 return_type: impl Into<String>,
46 ) -> Self {
47 Self {
48 name: name.into(),
49 params,
50 return_type: return_type.into(),
51 doc: None,
52 }
53 }
54
55 pub fn with_doc(mut self, doc: impl Into<String>) -> Self {
56 self.doc = Some(doc.into());
57 self
58 }
59
60 pub fn name(&self) -> &str {
61 &self.name
62 }
63
64 pub fn params(&self) -> &[NativeExportParam] {
65 &self.params
66 }
67
68 pub fn return_type(&self) -> &str {
69 &self.return_type
70 }
71
72 pub fn doc(&self) -> Option<&str> {
73 self.doc.as_deref()
74 }
75}
76impl VM {
77 pub fn new() -> Self {
78 Self::with_config(&LustConfig::default())
79 }
80
81 pub fn with_config(config: &LustConfig) -> Self {
82 let mut vm = Self {
83 jit: JitState::new(),
84 functions: Vec::new(),
85 natives: HashMap::new(),
86 globals: HashMap::new(),
87 call_stack: Vec::new(),
88 max_stack_depth: 1000,
89 pending_return_value: None,
90 pending_return_dest: None,
91 trace_recorder: None,
92 side_trace_context: None,
93 skip_next_trace_record: false,
94 trait_impls: HashMap::new(),
95 struct_tostring_cache: HashMap::new(),
96 struct_metadata: HashMap::new(),
97 call_until_depth: None,
98 task_manager: TaskManager::new(),
99 current_task: None,
100 pending_task_signal: None,
101 last_task_signal: None,
102 cycle_collector: cycle::CycleCollector::new(),
103 exported_natives: Vec::new(),
104 export_prefix_stack: Vec::new(),
105 exported_type_stubs: Vec::new(),
106 };
107 vm.jit.enabled = vm.jit.enabled && config.jit_enabled();
108 vm.trait_impls
109 .insert(("int".to_string(), "ToString".to_string()), true);
110 vm.trait_impls
111 .insert(("float".to_string(), "ToString".to_string()), true);
112 vm.trait_impls
113 .insert(("string".to_string(), "ToString".to_string()), true);
114 vm.trait_impls
115 .insert(("bool".to_string(), "ToString".to_string()), true);
116 vm.trait_impls
117 .insert(("int".to_string(), "Hashable".to_string()), true);
118 vm.trait_impls
119 .insert(("float".to_string(), "Hashable".to_string()), true);
120 vm.trait_impls
121 .insert(("string".to_string(), "Hashable".to_string()), true);
122 vm.trait_impls
123 .insert(("bool".to_string(), "Hashable".to_string()), true);
124 super::corelib::install_core_builtins(&mut vm);
125 #[cfg(feature = "std")]
126 for (name, func) in super::stdlib::create_stdlib(config) {
127 vm.register_native(name, func);
128 }
129
130 vm
131 }
132
133 pub(super) fn observe_value(&mut self, value: &Value) {
134 self.cycle_collector.register_value(value);
135 }
136
137 pub(super) fn maybe_collect_cycles(&mut self) {
138 let mut collector = mem::take(&mut self.cycle_collector);
139 collector.maybe_collect(self);
140 self.cycle_collector = collector;
141 }
142
143 pub fn with_current<F, R>(f: F) -> CoreResult<R, String>
144 where
145 F: FnOnce(&mut VM) -> CoreResult<R, String>,
146 {
147 let ptr_opt = super::with_vm_stack(|stack| stack.last().copied());
148 if let Some(ptr) = ptr_opt {
149 let vm = unsafe { &mut *ptr };
150 f(vm)
151 } else {
152 Err("task API requires a running VM".to_string())
153 }
154 }
155
156 pub fn load_functions(&mut self, functions: Vec<Function>) {
157 self.functions = functions;
158 }
159
160 pub fn register_structs(&mut self, defs: &HashMap<String, StructDef>) {
161 for (name, def) in defs {
162 let field_names: Vec<Rc<String>> = def
163 .fields
164 .iter()
165 .map(|field| Rc::new(field.name.clone()))
166 .collect();
167 let field_storage: Vec<FieldStorage> = def
168 .fields
169 .iter()
170 .map(|field| match field.ownership {
171 FieldOwnership::Weak => FieldStorage::Weak,
172 FieldOwnership::Strong => FieldStorage::Strong,
173 })
174 .collect();
175 let field_types: Vec<Type> = def.fields.iter().map(|field| field.ty.clone()).collect();
176 let weak_targets: Vec<Option<Type>> = def
177 .fields
178 .iter()
179 .map(|field| field.weak_target.clone())
180 .collect();
181 let layout = Rc::new(StructLayout::new(
182 def.name.clone(),
183 field_names,
184 field_storage,
185 field_types,
186 weak_targets,
187 ));
188 self.struct_metadata.insert(
189 name.clone(),
190 RuntimeStructInfo {
191 layout: layout.clone(),
192 },
193 );
194 if let Some(simple) = name.rsplit('.').next() {
195 self.struct_metadata.insert(
196 simple.to_string(),
197 RuntimeStructInfo {
198 layout: layout.clone(),
199 },
200 );
201 }
202 }
203 }
204
205 pub fn instantiate_struct(
206 &self,
207 struct_name: &str,
208 fields: Vec<(Rc<String>, Value)>,
209 ) -> Result<Value> {
210 let info =
211 self.struct_metadata
212 .get(struct_name)
213 .ok_or_else(|| LustError::RuntimeError {
214 message: format!("Unknown struct '{}'", struct_name),
215 })?;
216 Self::build_struct_value(struct_name, info, fields)
217 }
218
219 fn build_struct_value(
220 struct_name: &str,
221 info: &RuntimeStructInfo,
222 mut fields: Vec<(Rc<String>, Value)>,
223 ) -> Result<Value> {
224 let layout = info.layout.clone();
225 let field_count = layout.field_names().len();
226 let mut ordered = vec![Value::Nil; field_count];
227 let mut filled = vec![false; field_count];
228 for (field_name, field_value) in fields.drain(..) {
229 let index_opt = layout
230 .index_of_rc(&field_name)
231 .or_else(|| layout.index_of_str(field_name.as_str()));
232 let index = match index_opt {
233 Some(i) => i,
234 None => {
235 return Err(LustError::RuntimeError {
236 message: format!("Struct '{}' has no field '{}'", struct_name, field_name),
237 })
238 }
239 };
240 let canonical = layout
241 .canonicalize_field_value(index, field_value)
242 .map_err(|msg| LustError::RuntimeError { message: msg })?;
243 ordered[index] = canonical;
244 filled[index] = true;
245 }
246
247 if filled.iter().any(|slot| !*slot) {
248 let missing: Vec<String> = layout
249 .field_names()
250 .iter()
251 .enumerate()
252 .filter_map(|(idx, name)| (!filled[idx]).then(|| (**name).clone()))
253 .collect();
254 return Err(LustError::RuntimeError {
255 message: format!(
256 "Struct '{}' is missing required field(s): {}",
257 struct_name,
258 missing.join(", ")
259 ),
260 });
261 }
262
263 Ok(Value::Struct {
264 name: struct_name.to_string(),
265 layout,
266 fields: Rc::new(RefCell::new(ordered)),
267 })
268 }
269
270 pub fn register_trait_impl(&mut self, type_name: String, trait_name: String) {
271 self.trait_impls.insert((type_name, trait_name), true);
272 }
273
274 pub fn register_native(&mut self, name: impl Into<String>, value: Value) {
275 let name = name.into();
276 match value {
277 Value::NativeFunction(_) => {
278 let cloned = value.clone();
279 self.natives.insert(name.clone(), value);
280 self.globals.insert(name, cloned);
281 }
282
283 other => {
284 self.globals.insert(name, other);
285 }
286 }
287 }
288
289 pub(crate) fn push_export_prefix(&mut self, crate_name: &str) {
290 let sanitized = crate_name.replace('-', "_");
291 self.export_prefix_stack.push(sanitized);
292 }
293
294 pub(crate) fn pop_export_prefix(&mut self) {
295 self.export_prefix_stack.pop();
296 }
297
298 fn current_export_prefix(&self) -> Option<&str> {
299 self.export_prefix_stack.last().map(|s| s.as_str())
300 }
301
302 pub fn export_prefix(&self) -> Option<String> {
303 self.current_export_prefix().map(|s| s.to_string())
304 }
305
306 pub fn register_exported_native<F>(&mut self, export: NativeExport, func: F)
307 where
308 F: Fn(&[Value]) -> CoreResult<NativeCallResult, String> + 'static,
309 {
310 let mut export = export;
311 if let Some(prefix) = self.current_export_prefix() {
312 let needs_prefix = match export.name.strip_prefix(prefix) {
313 Some(rest) => {
314 if rest.is_empty() {
315 false
316 } else {
317 !matches!(rest.chars().next(), Some('.') | Some(':'))
318 }
319 }
320 None => true,
321 };
322 if needs_prefix {
323 export.name = if export.name.is_empty() {
324 prefix.to_string()
325 } else {
326 format!("{prefix}.{}", export.name)
327 };
328 }
329 }
330 let name = export.name.clone();
331 self.exported_natives.push(export);
332 let native = Value::NativeFunction(Rc::new(func));
333 self.register_native(name, native);
334 }
335
336 pub fn register_type_stubs(&mut self, stubs: Vec<ModuleStub>) {
337 if stubs.is_empty() {
338 return;
339 }
340 self.exported_type_stubs.extend(stubs);
341 }
342
343 pub fn take_type_stubs(&mut self) -> Vec<ModuleStub> {
344 mem::take(&mut self.exported_type_stubs)
345 }
346
347 pub fn exported_natives(&self) -> &[NativeExport] {
348 &self.exported_natives
349 }
350
351 pub fn take_exported_natives(&mut self) -> Vec<NativeExport> {
352 mem::take(&mut self.exported_natives)
353 }
354
355 pub fn clear_native_functions(&mut self) {
356 self.natives.clear();
357 self.exported_type_stubs.clear();
358 }
359
360 pub fn get_global(&self, name: &str) -> Option<Value> {
361 if let Some(value) = self.globals.get(name) {
362 Some(value.clone())
363 } else {
364 self.natives.get(name).cloned()
365 }
366 }
367
368 pub fn global_names(&self) -> Vec<String> {
369 self.globals.keys().cloned().collect()
370 }
371
372 pub fn globals_snapshot(&self) -> Vec<(String, Value)> {
373 self.globals
374 .iter()
375 .map(|(name, value)| (name.clone(), value.clone()))
376 .collect()
377 }
378
379 pub fn set_global(&mut self, name: impl Into<String>, value: Value) {
380 let name = name.into();
381 self.observe_value(&value);
382 self.globals.insert(name.clone(), value);
383 self.natives.remove(&name);
384 self.maybe_collect_cycles();
385 }
386
387 pub fn call(&mut self, function_name: &str, args: Vec<Value>) -> Result<Value> {
388 let func_idx = self
389 .functions
390 .iter()
391 .position(|f| f.name == function_name)
392 .ok_or_else(|| LustError::RuntimeError {
393 message: format!("Function not found: {}", function_name),
394 })?;
395 let mut frame = CallFrame {
396 function_idx: func_idx,
397 ip: 0,
398 registers: array::from_fn(|_| Value::Nil),
399 base_register: 0,
400 return_dest: None,
401 upvalues: Vec::new(),
402 };
403 let func = &self.functions[func_idx];
404 if args.len() != func.param_count as usize {
405 return Err(LustError::RuntimeError {
406 message: format!(
407 "Function {} expects {} arguments, got {}",
408 function_name,
409 func.param_count,
410 args.len()
411 ),
412 });
413 }
414
415 for (i, arg) in args.into_iter().enumerate() {
416 frame.registers[i] = arg;
417 }
418
419 self.call_stack.push(frame);
420 match self.run() {
421 Ok(v) => Ok(v),
422 Err(e) => Err(self.annotate_runtime_error(e)),
423 }
424 }
425
426 pub fn function_value(&self, function_name: &str) -> Option<Value> {
427 let canonical = if function_name.contains("::") {
428 function_name.replace("::", ".")
429 } else {
430 function_name.to_string()
431 };
432 self.functions
433 .iter()
434 .position(|f| f.name == canonical)
435 .map(Value::Function)
436 }
437
438 pub fn function_name(&self, index: usize) -> Option<&str> {
439 self.functions.get(index).map(|f| f.name.as_str())
440 }
441
442 pub fn fail_task_handle(&mut self, handle: TaskHandle, error: LustError) -> Result<()> {
443 let task_id = self.task_id_from_handle(handle)?;
444 let mut task =
445 self.task_manager
446 .detach(task_id)
447 .ok_or_else(|| LustError::RuntimeError {
448 message: format!("Invalid task handle {}", handle.id()),
449 })?;
450 task.state = TaskState::Failed;
451 task.error = Some(error.clone());
452 task.last_yield = None;
453 task.last_result = None;
454 task.yield_dest = None;
455 task.call_stack.clear();
456 task.pending_return_value = None;
457 task.pending_return_dest = None;
458 self.task_manager.attach(task);
459 Err(error)
460 }
461}