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