1use super::*;
2use core::{array, ptr};
3impl VM {
4 pub(super) fn push_current_vm(&mut self) {
5 let ptr = self as *mut VM;
6 crate::vm::push_vm_ptr(ptr);
7 }
8
9 pub(super) fn pop_current_vm(&mut self) {
10 crate::vm::pop_vm_ptr();
11 }
12
13 pub(super) fn run(&mut self) -> Result<Value> {
14 loop {
15 if let Some(target_depth) = self.call_until_depth {
16 if self.call_stack.len() == target_depth {
17 if let Some(return_value) = self.pending_return_value.take() {
18 self.call_until_depth = None;
19 return Ok(return_value);
20 }
21 }
22 }
23
24 if let Some(return_value) = self.pending_return_value.take() {
25 if let Some(dest_reg) = self.pending_return_dest.take() {
26 self.set_register(dest_reg, return_value)?;
27 }
28 }
29
30 if self.current_task.is_some() {
31 if let Some(signal) = self.pending_task_signal.take() {
32 self.last_task_signal = Some(signal);
33 return Ok(Value::Nil);
34 }
35 }
36
37 if self.call_stack.len() > self.max_stack_depth {
38 return Err(LustError::RuntimeError {
39 message: "Stack overflow".to_string(),
40 });
41 }
42
43 let executing_frame_index =
44 self.call_stack
45 .len()
46 .checked_sub(1)
47 .ok_or_else(|| LustError::RuntimeError {
48 message: "Empty call stack".to_string(),
49 })?;
50 let frame = self
51 .call_stack
52 .last_mut()
53 .ok_or_else(|| LustError::RuntimeError {
54 message: "Empty call stack".to_string(),
55 })?;
56 let (instruction, ip_before_execution, func_idx) = {
57 let func = &self.functions[frame.function_idx];
58 if frame.ip >= func.chunk.instructions.len() {
59 self.call_stack.pop();
60 if self.call_stack.is_empty() {
61 return Ok(Value::Nil);
62 }
63
64 continue;
65 }
66
67 let instruction = func.chunk.instructions[frame.ip];
68 frame.ip += 1;
69 let ip_before_execution = frame.ip;
70 let func_idx = frame.function_idx;
71 (instruction, ip_before_execution, func_idx)
72 };
73 let (should_check_jit, loop_start_ip) = if let Instruction::Jump(offset) = instruction {
74 if offset < 0 {
75 let current_frame = self.call_stack.last().unwrap();
76 let jump_target = (current_frame.ip as isize + offset as isize) as usize;
77 (true, jump_target)
78 } else {
79 (false, 0)
80 }
81 } else {
82 (false, 0)
83 };
84 if should_check_jit && self.jit.enabled {
85 let count = self.jit.profiler.record_backedge(func_idx, loop_start_ip);
86 if let Some(trace_id) = self
87 .jit
88 .root_traces
89 .get(&(func_idx, loop_start_ip))
90 .copied()
91 {
92 let frame = self.call_stack.last_mut().unwrap();
93 let registers_ptr = frame.registers.as_mut_ptr();
94 let entry = self.jit.get_trace(trace_id).map(|t| t.entry);
95 if let Some(entry_fn) = entry {
96 let result = entry_fn(registers_ptr, self as *mut VM, ptr::null());
97 if result == 0 {
98 if let Some(frame) = self.call_stack.last_mut() {
99 frame.ip = loop_start_ip;
100 }
101
102 continue;
103 } else if result > 0 {
104 let guard_index = (result - 1) as usize;
105 let side_trace_id = self
106 .jit
107 .get_trace(trace_id)
108 .and_then(|t| t.guards.get(guard_index))
109 .and_then(|g| g.side_trace);
110 if let Some(side_trace_id) = side_trace_id {
111 crate::jit::log(|| {
112 format!(
113 "🌳 JIT: Executing side trace #{} for guard #{}",
114 side_trace_id.0, guard_index
115 )
116 });
117 let frame = self.call_stack.last_mut().unwrap();
118 let registers_ptr = frame.registers.as_mut_ptr();
119 let side_entry = self.jit.get_trace(side_trace_id).map(|t| t.entry);
120 if let Some(side_entry_fn) = side_entry {
121 let side_result =
122 side_entry_fn(registers_ptr, self as *mut VM, ptr::null());
123 if side_result == 0 {
124 crate::jit::log(|| {
125 format!(
126 "✅ JIT: Side trace #{} executed successfully",
127 side_trace_id.0
128 )
129 });
130 } else {
131 crate::jit::log(|| {
132 format!(
133 "⚠️ JIT: Side trace #{} failed, falling back to interpreter",
134 side_trace_id.0
135 )
136 });
137 }
138 }
139 } else {
140 if let Some(trace) = self.jit.get_trace(trace_id) {
141 if let Some(g) = trace.guards.get(guard_index) {
142 if g.bailout_ip != 0 {
143 continue;
144 }
145 }
146 }
147
148 self.handle_guard_failure(trace_id, guard_index, func_idx)?;
149 self.jit.root_traces.remove(&(func_idx, loop_start_ip));
150 }
151 } else {
152 crate::jit::log(|| {
153 "⚠️ JIT: Trace execution failed (unknown error)".to_string()
154 });
155 if let Some(frame) = self.call_stack.last_mut() {
156 frame.ip = loop_start_ip;
157 }
158
159 self.jit.root_traces.remove(&(func_idx, loop_start_ip));
160 }
161 }
162 } else {
163 let is_side_trace = self.side_trace_context.is_some();
164 if is_side_trace {
165 if let Some(recorder) = &self.trace_recorder {
166 if !recorder.is_recording() {
167 crate::jit::log(|| {
168 format!(
169 "📝 JIT: Trace recording complete - {} ops recorded",
170 recorder.trace.ops.len()
171 )
172 });
173 let recorder = self.trace_recorder.take().unwrap();
174 let mut trace = recorder.finish();
175 let side_trace_ctx = self.side_trace_context.take().unwrap();
176 let mut optimizer = TraceOptimizer::new();
177 let hoisted_constants = optimizer.optimize(&mut trace);
178 let (parent_trace_id, guard_index) = side_trace_ctx;
179 crate::jit::log(|| {
180 format!(
181 "⚙️ JIT: Compiling side trace (parent: #{}, guard: {})...",
182 parent_trace_id.0, guard_index
183 )
184 });
185 let trace_id = self.jit.alloc_trace_id();
186 match JitCompiler::new().compile_trace(
187 &trace,
188 trace_id,
189 Some(parent_trace_id),
190 hoisted_constants.clone(),
191 ) {
192 Ok(compiled_trace) => {
193 crate::jit::log(|| {
194 format!(
195 "✅ JIT: Side trace #{} compiled successfully!",
196 trace_id.0
197 )
198 });
199 if let Some(parent) =
200 self.jit.get_trace_mut(parent_trace_id)
201 {
202 if guard_index < parent.guards.len() {
203 parent.guards[guard_index].side_trace =
204 Some(trace_id);
205 crate::jit::log(|| {
206 format!(
207 "🔗 JIT: Linked side trace #{} to parent trace #{} guard #{}",
208 trace_id.0, parent_trace_id.0, guard_index
209 )
210 });
211 }
212 }
213
214 self.jit.store_side_trace(compiled_trace);
215 }
216
217 Err(e) => {
218 crate::jit::log(|| {
219 format!("❌ JIT: Side trace compilation failed: {}", e)
220 });
221 }
222 }
223 }
224 }
225 } else {
226 if let Some(recorder) = &mut self.trace_recorder {
227 if recorder.is_recording() && count > crate::jit::HOT_THRESHOLD + 1 {
228 crate::jit::log(|| {
229 format!(
230 "📝 JIT: Trace recording complete - {} ops recorded",
231 recorder.trace.ops.len()
232 )
233 });
234 let recorder = self.trace_recorder.take().unwrap();
235 let mut trace = recorder.finish();
236 let mut optimizer = TraceOptimizer::new();
237 let hoisted_constants = optimizer.optimize(&mut trace);
238 crate::jit::log(|| "⚙️ JIT: Compiling root trace...".to_string());
239 let trace_id = self.jit.alloc_trace_id();
240 match JitCompiler::new().compile_trace(
241 &trace,
242 trace_id,
243 None,
244 hoisted_constants.clone(),
245 ) {
246 Ok(compiled_trace) => {
247 crate::jit::log(|| {
248 format!(
249 "✅ JIT: Trace #{} compiled successfully!",
250 trace_id.0
251 )
252 });
253 crate::jit::log(|| {
254 "🚀 JIT: Future iterations will use native code!"
255 .to_string()
256 });
257 self.jit.store_root_trace(
258 func_idx,
259 loop_start_ip,
260 compiled_trace,
261 );
262 }
263
264 Err(e) => {
265 crate::jit::log(|| {
266 format!("❌ JIT: Trace compilation failed: {}", e)
267 });
268 }
269 }
270 }
271 }
272
273 if count == crate::jit::HOT_THRESHOLD + 1 {
274 crate::jit::log(|| {
275 format!(
276 "🔥 JIT: Hot loop detected at func {} ip {} - starting trace recording!",
277 func_idx, loop_start_ip
278 )
279 });
280 self.trace_recorder = Some(TraceRecorder::new(
281 func_idx,
282 loop_start_ip,
283 MAX_TRACE_LENGTH,
284 ));
285 self.skip_next_trace_record = true;
286 }
287 }
288 }
289 }
290
291 match instruction {
292 Instruction::LoadNil(dest) => {
293 self.set_register(dest, Value::Nil)?;
294 }
295
296 Instruction::LoadBool(dest, value) => {
297 self.set_register(dest, Value::Bool(value))?;
298 }
299
300 Instruction::LoadConst(dest, const_idx) => {
301 let constant = {
302 let func = &self.functions[func_idx];
303 func.chunk.constants[const_idx as usize].clone()
304 };
305 self.set_register(dest, constant)?;
306 }
307
308 Instruction::LoadGlobal(dest, name_idx) => {
309 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
310 let name = func.chunk.constants[name_idx as usize]
311 .as_string()
312 .ok_or_else(|| LustError::RuntimeError {
313 message: "Global name must be a string".to_string(),
314 })?;
315 if let Some(value) = self.globals.get(name) {
316 self.set_register(dest, value.clone())?;
317 } else if let Some(value) = self.natives.get(name) {
318 self.set_register(dest, value.clone())?;
319 } else {
320 if let Some((_, value)) =
321 self.globals.iter().find(|(key, _)| key.as_str() == name)
322 {
323 self.set_register(dest, value.clone())?;
324 } else if let Some((_, value)) =
325 self.natives.iter().find(|(key, _)| key.as_str() == name)
326 {
327 self.set_register(dest, value.clone())?;
328 } else {
329 return Err(LustError::RuntimeError {
330 message: format!("Undefined global: {}", name),
331 });
332 }
333 }
334 }
335
336 Instruction::StoreGlobal(name_idx, src) => {
337 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
338 let name = func.chunk.constants[name_idx as usize]
339 .as_string()
340 .ok_or_else(|| LustError::RuntimeError {
341 message: "Global name must be a string".to_string(),
342 })?;
343 let value = self.get_register(src)?.clone();
344 self.globals.insert(name.to_string(), value);
345 }
346
347 Instruction::Move(dest, src) => {
348 let value = self.get_register(src)?.clone();
349 self.set_register(dest, value)?;
350 }
351
352 Instruction::Add(dest, lhs, rhs) => {
353 self.binary_op(dest, lhs, rhs, |l, r| match (l, r) {
354 (Value::Int(a), Value::Int(b)) => Ok(Value::Int(a + b)),
355 (Value::Float(a), Value::Float(b)) => Ok(Value::Float(a + b)),
356 (Value::Int(a), Value::Float(b)) => {
357 Ok(Value::Float(float_from_int(*a) + *b))
358 }
359 (Value::Float(a), Value::Int(b)) => {
360 Ok(Value::Float(*a + float_from_int(*b)))
361 }
362 _ => Err(LustError::RuntimeError {
363 message: format!("Cannot add {:?} and {:?}", l, r),
364 }),
365 })?;
366 }
367
368 Instruction::Sub(dest, lhs, rhs) => {
369 self.binary_op(dest, lhs, rhs, |l, r| match (l, r) {
370 (Value::Int(a), Value::Int(b)) => Ok(Value::Int(a - b)),
371 (Value::Float(a), Value::Float(b)) => Ok(Value::Float(a - b)),
372 (Value::Int(a), Value::Float(b)) => {
373 Ok(Value::Float(float_from_int(*a) - *b))
374 }
375 (Value::Float(a), Value::Int(b)) => {
376 Ok(Value::Float(*a - float_from_int(*b)))
377 }
378 _ => Err(LustError::RuntimeError {
379 message: format!("Cannot subtract {:?} and {:?}", l, r),
380 }),
381 })?;
382 }
383
384 Instruction::Mul(dest, lhs, rhs) => {
385 self.binary_op(dest, lhs, rhs, |l, r| match (l, r) {
386 (Value::Int(a), Value::Int(b)) => Ok(Value::Int(a * b)),
387 (Value::Float(a), Value::Float(b)) => Ok(Value::Float(a * b)),
388 (Value::Int(a), Value::Float(b)) => {
389 Ok(Value::Float(float_from_int(*a) * *b))
390 }
391 (Value::Float(a), Value::Int(b)) => {
392 Ok(Value::Float(*a * float_from_int(*b)))
393 }
394 _ => Err(LustError::RuntimeError {
395 message: format!("Cannot multiply {:?} and {:?}", l, r),
396 }),
397 })?;
398 }
399
400 Instruction::Div(dest, lhs, rhs) => {
401 self.binary_op(dest, lhs, rhs, |l, r| match (l, r) {
402 (Value::Int(a), Value::Int(b)) => {
403 if *b == 0 {
404 Err(LustError::RuntimeError {
405 message: "Division by zero".to_string(),
406 })
407 } else {
408 Ok(Value::Int(a / b))
409 }
410 }
411
412 (Value::Float(a), Value::Float(b)) => Ok(Value::Float(*a / *b)),
413 (Value::Int(a), Value::Float(b)) => {
414 Ok(Value::Float(float_from_int(*a) / *b))
415 }
416 (Value::Float(a), Value::Int(b)) => {
417 Ok(Value::Float(*a / float_from_int(*b)))
418 }
419 _ => Err(LustError::RuntimeError {
420 message: format!("Cannot divide {:?} and {:?}", l, r),
421 }),
422 })?;
423 }
424
425 Instruction::Mod(dest, lhs, rhs) => {
426 self.binary_op(dest, lhs, rhs, |l, r| match (l, r) {
427 (Value::Int(a), Value::Int(b)) => {
428 if *b == 0 {
429 Err(LustError::RuntimeError {
430 message: "Modulo by zero".to_string(),
431 })
432 } else {
433 Ok(Value::Int(a % b))
434 }
435 }
436
437 (Value::Float(a), Value::Float(b)) => {
438 if *b == 0.0 {
439 Err(LustError::RuntimeError {
440 message: "Modulo by zero".to_string(),
441 })
442 } else {
443 Ok(Value::Float(a % b))
444 }
445 }
446
447 (Value::Int(a), Value::Float(b)) => {
448 if *b == 0.0 {
449 Err(LustError::RuntimeError {
450 message: "Modulo by zero".to_string(),
451 })
452 } else {
453 Ok(Value::Float(float_from_int(*a) % *b))
454 }
455 }
456
457 (Value::Float(a), Value::Int(b)) => {
458 if *b == 0 {
459 Err(LustError::RuntimeError {
460 message: "Modulo by zero".to_string(),
461 })
462 } else {
463 Ok(Value::Float(*a % float_from_int(*b)))
464 }
465 }
466
467 _ => Err(LustError::RuntimeError {
468 message: format!("Cannot modulo {:?} and {:?}", l, r),
469 }),
470 })?;
471 }
472
473 Instruction::Neg(dest, src) => {
474 let value = self.get_register(src)?;
475 let result = match value {
476 Value::Int(i) => Value::Int(-i),
477 Value::Float(f) => Value::Float(-f),
478 _ => {
479 return Err(LustError::RuntimeError {
480 message: format!("Cannot negate {:?}", value),
481 })
482 }
483 };
484 self.set_register(dest, result)?;
485 }
486
487 Instruction::Eq(dest, lhs, rhs) => {
488 let left = self.get_register(lhs)?;
489 let right = self.get_register(rhs)?;
490 self.set_register(dest, Value::Bool(left == right))?;
491 }
492
493 Instruction::Ne(dest, lhs, rhs) => {
494 let left = self.get_register(lhs)?;
495 let right = self.get_register(rhs)?;
496 self.set_register(dest, Value::Bool(left != right))?;
497 }
498
499 Instruction::Lt(dest, lhs, rhs) => {
500 self.comparison_op(dest, lhs, rhs, |l, r| l < r)?;
501 }
502
503 Instruction::Le(dest, lhs, rhs) => {
504 self.comparison_op(dest, lhs, rhs, |l, r| l <= r)?;
505 }
506
507 Instruction::Gt(dest, lhs, rhs) => {
508 self.comparison_op(dest, lhs, rhs, |l, r| l > r)?;
509 }
510
511 Instruction::Ge(dest, lhs, rhs) => {
512 self.comparison_op(dest, lhs, rhs, |l, r| l >= r)?;
513 }
514
515 Instruction::And(dest, lhs, rhs) => {
516 let left = self.get_register(lhs)?;
517 let right = self.get_register(rhs)?;
518 let result = Value::Bool(left.is_truthy() && right.is_truthy());
519 self.set_register(dest, result)?;
520 }
521
522 Instruction::Or(dest, lhs, rhs) => {
523 let left = self.get_register(lhs)?;
524 let right = self.get_register(rhs)?;
525 let result = Value::Bool(left.is_truthy() || right.is_truthy());
526 self.set_register(dest, result)?;
527 }
528
529 Instruction::Not(dest, src) => {
530 let value = self.get_register(src)?;
531 self.set_register(dest, Value::Bool(!value.is_truthy()))?;
532 }
533
534 Instruction::Jump(offset) => {
535 let frame = self.call_stack.last_mut().unwrap();
536 frame.ip = (frame.ip as isize + offset as isize) as usize;
537 }
538
539 Instruction::JumpIf(cond, offset) => {
540 let condition = self.get_register(cond)?;
541 if condition.is_truthy() {
542 let frame = self.call_stack.last_mut().unwrap();
543 frame.ip = (frame.ip as isize + offset as isize) as usize;
544 }
545 }
546
547 Instruction::JumpIfNot(cond, offset) => {
548 let condition = self.get_register(cond)?;
549 if !condition.is_truthy() {
550 let frame = self.call_stack.last_mut().unwrap();
551 frame.ip = (frame.ip as isize + offset as isize) as usize;
552 }
553 }
554
555 Instruction::Call(func_reg, first_arg, arg_count, dest_reg) => {
556 let func_value = self.get_register(func_reg)?.clone();
557 match func_value {
558 Value::Function(func_idx) => {
559 let mut args = Vec::new();
560 for i in 0..arg_count {
561 args.push(self.get_register(first_arg + i)?.clone());
562 }
563
564 let mut frame = CallFrame {
565 function_idx: func_idx,
566 ip: 0,
567 registers: array::from_fn(|_| Value::Nil),
568 base_register: 0,
569 return_dest: Some(dest_reg),
570 upvalues: Vec::new(),
571 };
572 for (i, arg) in args.into_iter().enumerate() {
573 frame.registers[i] = arg;
574 }
575
576 self.call_stack.push(frame);
577 }
578
579 Value::Closure {
580 function_idx: func_idx,
581 upvalues,
582 } => {
583 let mut args = Vec::new();
584 for i in 0..arg_count {
585 args.push(self.get_register(first_arg + i)?.clone());
586 }
587
588 let upvalue_values: Vec<Value> =
589 upvalues.iter().map(|uv| uv.get()).collect();
590 let mut frame = CallFrame {
591 function_idx: func_idx,
592 ip: 0,
593 registers: array::from_fn(|_| Value::Nil),
594 base_register: 0,
595 return_dest: Some(dest_reg),
596 upvalues: upvalue_values,
597 };
598 for (i, arg) in args.into_iter().enumerate() {
599 frame.registers[i] = arg;
600 }
601
602 self.call_stack.push(frame);
603 }
604
605 Value::NativeFunction(native_fn) => {
606 let mut args = Vec::new();
607 for i in 0..arg_count {
608 args.push(self.get_register(first_arg + i)?.clone());
609 }
610
611 self.push_current_vm();
612 let outcome = native_fn(&args);
613 self.pop_current_vm();
614 let outcome =
615 outcome.map_err(|e| LustError::RuntimeError { message: e })?;
616 self.handle_native_call_outcome(dest_reg, outcome)?;
617 }
618
619 _ => {
620 return Err(LustError::RuntimeError {
621 message: format!(
622 "Cannot call non-function value: {:?}",
623 func_value
624 ),
625 })
626 }
627 }
628 }
629
630 Instruction::Return(value_reg) => {
631 let return_value = if value_reg == 255 {
632 Value::Nil
633 } else {
634 self.get_register(value_reg)?.clone()
635 };
636 let return_dest = self.call_stack.last().unwrap().return_dest;
637 self.call_stack.pop();
638 if self.call_stack.is_empty() {
639 return Ok(return_value);
640 }
641
642 self.pending_return_value = Some(return_value);
643 self.pending_return_dest = return_dest;
644 }
645
646 Instruction::NewArray(dest, first_elem, count) => {
647 let mut elements = Vec::new();
648 for i in 0..count {
649 elements.push(self.get_register(first_elem + i)?.clone());
650 }
651
652 self.set_register(dest, Value::array(elements))?;
653 }
654
655 Instruction::TupleNew(dest, first_elem, count) => {
656 let mut elements = Vec::new();
657 for offset in 0..(count as usize) {
658 let value = self.get_register(first_elem + offset as u8)?.clone();
659 if let Value::Tuple(existing) = value {
660 elements.extend(existing.iter().cloned());
661 } else {
662 elements.push(value);
663 }
664 }
665
666 self.set_register(dest, Value::tuple(elements))?;
667 }
668
669 Instruction::TupleGet(dest, tuple_reg, index) => {
670 let tuple_value = self.get_register(tuple_reg)?.clone();
671 if let Value::Tuple(values) = tuple_value {
672 let idx = index as usize;
673 if idx >= values.len() {
674 return Err(LustError::RuntimeError {
675 message: format!(
676 "Tuple index {} out of bounds (len {})",
677 idx,
678 values.len()
679 ),
680 });
681 }
682
683 let value = values[idx].clone();
684 self.set_register(dest, value)?;
685 } else {
686 return Err(LustError::RuntimeError {
687 message: "Attempted to destructure non-tuple value".to_string(),
688 });
689 }
690 }
691
692 Instruction::NewMap(dest) => {
693 self.set_register(dest, Value::map(HashMap::new()))?;
694 }
695
696 Instruction::NewStruct(
697 dest,
698 name_idx,
699 first_field_name_idx,
700 first_field,
701 field_count,
702 ) => {
703 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
704 let struct_name = func.chunk.constants[name_idx as usize]
705 .as_string()
706 .ok_or_else(|| LustError::RuntimeError {
707 message: "Struct name must be a string".to_string(),
708 })?
709 .to_string();
710 let mut fields = Vec::with_capacity(field_count as usize);
711 for i in 0..field_count {
712 let field_name = func.chunk.constants
713 [(first_field_name_idx + i as u16) as usize]
714 .as_string_rc()
715 .ok_or_else(|| LustError::RuntimeError {
716 message: "Field name must be a string".to_string(),
717 })?;
718 let value = self.get_register(first_field + i)?.clone();
719 fields.push((field_name, value));
720 }
721
722 let struct_value = self.instantiate_struct(&struct_name, fields)?;
723 self.set_register(dest, struct_value)?;
724 }
725
726 Instruction::NewEnumUnit(dest, enum_name_idx, variant_idx) => {
727 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
728 let enum_name = func.chunk.constants[enum_name_idx as usize]
729 .as_string()
730 .ok_or_else(|| LustError::RuntimeError {
731 message: "Enum name must be a string".to_string(),
732 })?
733 .to_string();
734 let variant_name = func.chunk.constants[variant_idx as usize]
735 .as_string()
736 .ok_or_else(|| LustError::RuntimeError {
737 message: "Variant name must be a string".to_string(),
738 })?
739 .to_string();
740 self.set_register(dest, Value::enum_unit(enum_name, variant_name))?;
741 }
742
743 Instruction::NewEnumVariant(
744 dest,
745 enum_name_idx,
746 variant_idx,
747 first_value,
748 value_count,
749 ) => {
750 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
751 let enum_name = func.chunk.constants[enum_name_idx as usize]
752 .as_string()
753 .ok_or_else(|| LustError::RuntimeError {
754 message: "Enum name must be a string".to_string(),
755 })?
756 .to_string();
757 let variant_name = func.chunk.constants[variant_idx as usize]
758 .as_string()
759 .ok_or_else(|| LustError::RuntimeError {
760 message: "Variant name must be a string".to_string(),
761 })?
762 .to_string();
763 let mut values = Vec::new();
764 for i in 0..value_count {
765 values.push(self.get_register(first_value + i)?.clone());
766 }
767
768 self.set_register(dest, Value::enum_variant(enum_name, variant_name, values))?;
769 }
770
771 Instruction::IsEnumVariant(dest, value_reg, enum_name_idx, variant_idx) => {
772 let value = self.get_register(value_reg)?;
773 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
774 let enum_name = func.chunk.constants[enum_name_idx as usize]
775 .as_string()
776 .ok_or_else(|| LustError::RuntimeError {
777 message: "Enum name must be a string".to_string(),
778 })?;
779 let variant_name = func.chunk.constants[variant_idx as usize]
780 .as_string()
781 .ok_or_else(|| LustError::RuntimeError {
782 message: "Variant name must be a string".to_string(),
783 })?;
784 let is_variant = value.is_enum_variant(enum_name, variant_name);
785 self.set_register(dest, Value::Bool(is_variant))?;
786 }
787
788 Instruction::GetEnumValue(dest, enum_reg, index) => {
789 let enum_value = self.get_register(enum_reg)?;
790 if let Some((_, _, Some(values))) = enum_value.as_enum() {
791 if (index as usize) < values.len() {
792 self.set_register(dest, values[index as usize].clone())?;
793 } else {
794 return Err(LustError::RuntimeError {
795 message: format!(
796 "Enum value index {} out of bounds (has {} values)",
797 index,
798 values.len()
799 ),
800 });
801 }
802 } else {
803 return Err(LustError::RuntimeError {
804 message: "GetEnumValue requires an enum variant with values"
805 .to_string(),
806 });
807 }
808 }
809
810 Instruction::GetField(dest, obj, field_idx) => {
811 let object = self.get_register(obj)?;
812 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
813 let field_name = func.chunk.constants[field_idx as usize]
814 .as_string_rc()
815 .ok_or_else(|| LustError::RuntimeError {
816 message: "Field name must be a string".to_string(),
817 })?;
818 let value = match object {
819 Value::Struct { .. } => object
820 .struct_get_field_rc(&field_name)
821 .unwrap_or(Value::Nil),
822 Value::Map(map) => {
823 use crate::bytecode::ValueKey;
824 let key = ValueKey::String(field_name.clone());
825 map.borrow().get(&key).cloned().unwrap_or(Value::Nil)
826 }
827
828 _ => {
829 return Err(LustError::RuntimeError {
830 message: format!(
831 "Cannot get field '{}' from {:?}",
832 field_name.as_str(),
833 object
834 ),
835 })
836 }
837 };
838 self.set_register(dest, value)?;
839 }
840
841 Instruction::SetField(obj_reg, field_idx, value_reg) => {
842 let object = self.get_register(obj_reg)?;
843 let value = self.get_register(value_reg)?.clone();
844 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
845 let field_name = func.chunk.constants[field_idx as usize]
846 .as_string_rc()
847 .ok_or_else(|| LustError::RuntimeError {
848 message: "Field name must be a string".to_string(),
849 })?;
850 let mut invalidate_key: Option<usize> = None;
851 match object {
852 Value::Struct { .. } => {
853 invalidate_key = Self::struct_cache_key(object);
854 object
855 .struct_set_field_rc(&field_name, value)
856 .map_err(|message| LustError::RuntimeError { message })?;
857 }
858
859 Value::Map(map) => {
860 use crate::bytecode::ValueKey;
861 let key = ValueKey::String(field_name.clone());
862 map.borrow_mut().insert(key, value);
863 }
864
865 _ => {
866 return Err(LustError::RuntimeError {
867 message: format!(
868 "Cannot set field '{}' on {:?}",
869 field_name.as_str(),
870 object
871 ),
872 })
873 }
874 }
875
876 if let Some(key) = invalidate_key {
877 self.struct_tostring_cache.remove(&key);
878 }
879 }
880
881 Instruction::Concat(dest, lhs, rhs) => {
882 let (left, right) = {
883 let frame =
884 self.call_stack
885 .last_mut()
886 .ok_or_else(|| LustError::RuntimeError {
887 message: "Empty call stack".to_string(),
888 })?;
889 let left = frame.registers[lhs as usize].clone();
890 let right = frame.registers[rhs as usize].clone();
891 (left, right)
892 };
893 let left_str = self.value_to_string_for_concat(&left)?;
894 let right_str = self.value_to_string_for_concat(&right)?;
895 let mut combined = String::with_capacity(left_str.len() + right_str.len());
896 combined.push_str(left_str.as_ref());
897 combined.push_str(right_str.as_ref());
898 let result = Value::string(combined);
899 self.set_register(dest, result)?;
900 }
901
902 Instruction::GetIndex(dest, array_reg, index_reg) => {
903 let collection = self.get_register(array_reg)?;
904 let index = self.get_register(index_reg)?;
905 let result = match collection {
906 Value::Array(arr) => {
907 let idx = index.as_int().ok_or_else(|| LustError::RuntimeError {
908 message: "Array index must be an integer".to_string(),
909 })?;
910 let borrowed = arr.borrow();
911 if idx < 0 || idx as usize >= borrowed.len() {
912 return Err(LustError::RuntimeError {
913 message: format!(
914 "Array index {} out of bounds (length: {})",
915 idx,
916 borrowed.len()
917 ),
918 });
919 }
920
921 borrowed[idx as usize].clone()
922 }
923
924 Value::Map(map) => {
925 use crate::bytecode::ValueKey;
926 let key = ValueKey::from_value(index).ok_or_else(|| {
927 LustError::RuntimeError {
928 message: format!(
929 "Cannot use {:?} as map key (not hashable)",
930 index
931 ),
932 }
933 })?;
934 map.borrow().get(&key).cloned().unwrap_or(Value::Nil)
935 }
936
937 _ => {
938 return Err(LustError::RuntimeError {
939 message: format!("Cannot index {:?}", collection.type_of()),
940 })
941 }
942 };
943 self.set_register(dest, result)?;
944 }
945
946 Instruction::ArrayLen(dest, array_reg) => {
947 let collection = self.get_register(array_reg)?;
948 match collection {
949 Value::Array(arr) => {
950 let len = int_from_usize(arr.borrow().len());
951 self.set_register(dest, Value::Int(len))?;
952 }
953
954 _ => {
955 return Err(LustError::RuntimeError {
956 message: format!(
957 "ArrayLen requires array, got {:?}",
958 collection.type_of()
959 ),
960 });
961 }
962 }
963 }
964
965 Instruction::CallMethod(
966 obj_reg,
967 method_name_idx,
968 first_arg,
969 arg_count,
970 dest_reg,
971 ) => {
972 let object = self.get_register(obj_reg)?.clone();
973 let method_name = {
974 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
975 func.chunk.constants[method_name_idx as usize]
976 .as_string()
977 .ok_or_else(|| LustError::RuntimeError {
978 message: "Method name must be a string".to_string(),
979 })?
980 .to_string()
981 };
982 if let Value::Struct {
983 name: struct_name, ..
984 } = &object
985 {
986 let mangled_name = format!("{}:{}", struct_name, method_name);
987 if let Some(func_idx) =
988 self.functions.iter().position(|f| f.name == mangled_name)
989 {
990 let mut frame = CallFrame {
991 function_idx: func_idx,
992 ip: 0,
993 registers: array::from_fn(|_| Value::Nil),
994 base_register: 0,
995 return_dest: Some(dest_reg),
996 upvalues: Vec::new(),
997 };
998 frame.registers[0] = object.clone();
999 for i in 0..arg_count {
1000 frame.registers[(i + 1) as usize] =
1001 self.get_register(first_arg + i)?.clone();
1002 }
1003
1004 self.call_stack.push(frame);
1005 continue;
1006 }
1007
1008 let mut candidate_names = vec![mangled_name.clone()];
1009 if let Some(simple) = struct_name.rsplit(|c| c == '.' || c == ':').next() {
1010 candidate_names.push(format!("{}:{}", simple, method_name));
1011 }
1012
1013 let mut handled = false;
1014 for candidate in candidate_names {
1015 let mut resolved = None;
1016 for variant in [candidate.clone(), candidate.replace('.', "::")] {
1017 if let Some((_name, value)) =
1018 self.globals.iter().find(|(name, _)| *name == &variant)
1019 {
1020 resolved = Some(value.clone());
1021 break;
1022 }
1023 if let Some((_name, value)) =
1024 self.natives.iter().find(|(name, _)| *name == &variant)
1025 {
1026 resolved = Some(value.clone());
1027 break;
1028 }
1029 }
1030
1031 if let Some(global_func) = resolved {
1032 let mut call_args = Vec::with_capacity(1 + arg_count as usize);
1033 call_args.push(object.clone());
1034 for i in 0..arg_count {
1035 call_args.push(self.get_register(first_arg + i)?.clone());
1036 }
1037 let result = self.call_value(&global_func, call_args)?;
1038 self.set_register(dest_reg, result)?;
1039 handled = true;
1040 break;
1041 }
1042 }
1043 if handled {
1044 continue;
1045 }
1046 }
1047
1048 let mut args = Vec::new();
1049 for i in 0..arg_count {
1050 args.push(self.get_register(first_arg + i)?.clone());
1051 }
1052
1053 let result = self.call_builtin_method(&object, &method_name, args)?;
1054 self.set_register(dest_reg, result)?;
1055 }
1056
1057 Instruction::Closure(dest, func_idx, first_upvalue_reg, upvalue_count) => {
1058 use crate::bytecode::Upvalue;
1059 let mut upvalues = Vec::new();
1060 for i in 0..upvalue_count {
1061 let value = self.get_register(first_upvalue_reg + i)?.clone();
1062 upvalues.push(Upvalue::new(value));
1063 }
1064
1065 let closure = Value::Closure {
1066 function_idx: func_idx as usize,
1067 upvalues: Rc::new(upvalues),
1068 };
1069 self.set_register(dest, closure)?;
1070 }
1071
1072 Instruction::LoadUpvalue(dest, upvalue_idx) => {
1073 let frame = self
1074 .call_stack
1075 .last()
1076 .ok_or_else(|| LustError::RuntimeError {
1077 message: "Empty call stack".to_string(),
1078 })?;
1079 if (upvalue_idx as usize) < frame.upvalues.len() {
1080 let value = frame.upvalues[upvalue_idx as usize].clone();
1081 self.set_register(dest, value)?;
1082 } else {
1083 return Err(LustError::RuntimeError {
1084 message: format!(
1085 "Upvalue index {} out of bounds (have {} upvalues)",
1086 upvalue_idx,
1087 frame.upvalues.len()
1088 ),
1089 });
1090 }
1091 }
1092
1093 Instruction::StoreUpvalue(upvalue_idx, src) => {
1094 let value = self.get_register(src)?.clone();
1095 let frame =
1096 self.call_stack
1097 .last_mut()
1098 .ok_or_else(|| LustError::RuntimeError {
1099 message: "Empty call stack".to_string(),
1100 })?;
1101 if (upvalue_idx as usize) < frame.upvalues.len() {
1102 frame.upvalues[upvalue_idx as usize] = value;
1103 } else {
1104 return Err(LustError::RuntimeError {
1105 message: format!(
1106 "Upvalue index {} out of bounds (have {} upvalues)",
1107 upvalue_idx,
1108 frame.upvalues.len()
1109 ),
1110 });
1111 }
1112 }
1113
1114 Instruction::SetIndex(collection_reg, index_reg, value_reg) => {
1115 let collection = self.get_register(collection_reg)?;
1116 let index = self.get_register(index_reg)?;
1117 let value = self.get_register(value_reg)?.clone();
1118 match collection {
1119 Value::Array(arr) => {
1120 let idx = index.as_int().ok_or_else(|| LustError::RuntimeError {
1121 message: "Array index must be an integer".to_string(),
1122 })?;
1123 let mut borrowed = arr.borrow_mut();
1124 if idx < 0 || idx as usize >= borrowed.len() {
1125 return Err(LustError::RuntimeError {
1126 message: format!(
1127 "Array index {} out of bounds (length: {})",
1128 idx,
1129 borrowed.len()
1130 ),
1131 });
1132 }
1133
1134 borrowed[idx as usize] = value;
1135 }
1136
1137 Value::Map(map) => {
1138 use crate::bytecode::ValueKey;
1139 let key = ValueKey::from_value(index).ok_or_else(|| {
1140 LustError::RuntimeError {
1141 message: format!(
1142 "Cannot use {:?} as map key (not hashable)",
1143 index
1144 ),
1145 }
1146 })?;
1147 map.borrow_mut().insert(key, value);
1148 }
1149
1150 _ => {
1151 return Err(LustError::RuntimeError {
1152 message: format!("Cannot index {:?}", collection.type_of()),
1153 })
1154 }
1155 }
1156 }
1157
1158 Instruction::TypeIs(dest, value_reg, type_name_idx) => {
1159 let value = self.get_register(value_reg)?.clone();
1160 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
1161 let type_name = func.chunk.constants[type_name_idx as usize]
1162 .as_string()
1163 .ok_or_else(|| LustError::RuntimeError {
1164 message: "Type name must be a string".to_string(),
1165 })?
1166 .to_string();
1167 let matches = self.value_is_type(&value, &type_name);
1168 self.set_register(dest, Value::Bool(matches))?;
1169 }
1170 }
1171
1172 if self.jit.enabled {
1173 if let Some(recorder) = &mut self.trace_recorder {
1174 if recorder.is_recording() {
1175 if self.skip_next_trace_record {
1176 self.skip_next_trace_record = false;
1177 } else {
1178 let function = &self.functions[func_idx];
1179 let registers_opt =
1180 if let Some(frame) = self.call_stack.get(executing_frame_index) {
1181 Some(&frame.registers)
1182 } else if executing_frame_index > 0 {
1183 self.call_stack
1184 .get(executing_frame_index - 1)
1185 .map(|frame| &frame.registers)
1186 } else {
1187 None
1188 };
1189 if let Some(registers) = registers_opt {
1190 if let Err(e) = recorder.record_instruction(
1191 instruction,
1192 ip_before_execution,
1193 registers,
1194 function,
1195 func_idx,
1196 &self.functions,
1197 ) {
1198 crate::jit::log(|| format!("⚠️ JIT: {}", e));
1199 self.trace_recorder = None;
1200 }
1201 }
1202 }
1203 }
1204 }
1205 }
1206 }
1207 }
1208
1209 pub(super) fn binary_op<F>(
1210 &mut self,
1211 dest: Register,
1212 lhs: Register,
1213 rhs: Register,
1214 op: F,
1215 ) -> Result<()>
1216 where
1217 F: FnOnce(&Value, &Value) -> Result<Value>,
1218 {
1219 let left = self.get_register(lhs)?;
1220 let right = self.get_register(rhs)?;
1221 let result = op(left, right)?;
1222 self.set_register(dest, result)
1223 }
1224
1225 pub(super) fn comparison_op<F>(
1226 &mut self,
1227 dest: Register,
1228 lhs: Register,
1229 rhs: Register,
1230 op: F,
1231 ) -> Result<()>
1232 where
1233 F: FnOnce(LustFloat, LustFloat) -> bool,
1234 {
1235 let left = self.get_register(lhs)?;
1236 let right = self.get_register(rhs)?;
1237 let result = match (left, right) {
1238 (Value::Int(a), Value::Int(b)) => op(float_from_int(*a), float_from_int(*b)),
1239 (Value::Float(a), Value::Float(b)) => op(*a, *b),
1240 (Value::Int(a), Value::Float(b)) => op(float_from_int(*a), *b),
1241 (Value::Float(a), Value::Int(b)) => op(*a, float_from_int(*b)),
1242 _ => {
1243 return Err(LustError::RuntimeError {
1244 message: format!("Cannot compare {:?} and {:?}", left, right),
1245 })
1246 }
1247 };
1248 self.set_register(dest, Value::Bool(result))
1249 }
1250
1251 pub(super) fn value_is_type(&self, value: &Value, type_name: &str) -> bool {
1252 let value_type_name = match value {
1253 Value::Int(_) => "int",
1254 Value::Float(_) => "float",
1255 Value::String(_) => "string",
1256 Value::Bool(_) => "bool",
1257 Value::Nil => "nil",
1258 Value::Array(_) => "Array",
1259 Value::Tuple(_) => "Tuple",
1260 Value::Map(_) => "Map",
1261 Value::Struct { name, .. } => name.as_str(),
1262 Value::WeakStruct(weak) => weak.struct_name(),
1263 Value::Enum { enum_name, .. } => enum_name.as_str(),
1264 Value::Function(_) | Value::NativeFunction(_) | Value::Closure { .. } => "function",
1265 Value::Iterator(_) => "Iterator",
1266 Value::Task(_) => "task",
1267 };
1268 if value_type_name == type_name {
1269 return true;
1270 }
1271
1272 if type_name.starts_with("Array") && matches!(value, Value::Array(_)) {
1273 return true;
1274 }
1275
1276 if type_name.starts_with("Map") && matches!(value, Value::Map(_)) {
1277 return true;
1278 }
1279
1280 if type_name.starts_with("Tuple") && matches!(value, Value::Tuple(_)) {
1281 return true;
1282 }
1283
1284 if type_name == "Option"
1285 && matches!(value, Value::Enum { enum_name, .. } if enum_name == "Option")
1286 {
1287 return true;
1288 }
1289
1290 if type_name == "Result"
1291 && matches!(value, Value::Enum { enum_name, .. } if enum_name == "Result")
1292 {
1293 return true;
1294 }
1295
1296 if type_name == "unknown" {
1297 return true;
1298 }
1299
1300 if let Some(_) = self
1301 .trait_impls
1302 .get(&(value_type_name.to_string(), type_name.to_string()))
1303 {
1304 return true;
1305 }
1306
1307 false
1308 }
1309
1310 pub(super) fn get_register(&self, reg: Register) -> Result<&Value> {
1311 let frame = self
1312 .call_stack
1313 .last()
1314 .ok_or_else(|| LustError::RuntimeError {
1315 message: "Empty call stack".to_string(),
1316 })?;
1317 Ok(&frame.registers[reg as usize])
1318 }
1319
1320 pub(super) fn set_register(&mut self, reg: Register, value: Value) -> Result<()> {
1321 self.observe_value(&value);
1322 let frame = self
1323 .call_stack
1324 .last_mut()
1325 .ok_or_else(|| LustError::RuntimeError {
1326 message: "Empty call stack".to_string(),
1327 })?;
1328 frame.registers[reg as usize] = value;
1329 self.maybe_collect_cycles();
1330 Ok(())
1331 }
1332
1333 pub(super) fn handle_native_call_outcome(
1334 &mut self,
1335 dest: Register,
1336 outcome: NativeCallResult,
1337 ) -> Result<()> {
1338 match outcome {
1339 NativeCallResult::Return(value) => self.set_register(dest, value),
1340 NativeCallResult::Yield(value) => {
1341 if self.current_task.is_some() {
1342 self.set_register(dest, Value::Nil)?;
1343 self.pending_task_signal = Some(TaskSignal::Yield { dest, value });
1344 Ok(())
1345 } else {
1346 Err(LustError::RuntimeError {
1347 message: "task.yield() can only be used inside a task".to_string(),
1348 })
1349 }
1350 }
1351
1352 NativeCallResult::Stop(value) => {
1353 if self.current_task.is_some() {
1354 self.set_register(dest, Value::Nil)?;
1355 self.pending_task_signal = Some(TaskSignal::Stop { value });
1356 Ok(())
1357 } else {
1358 Err(LustError::RuntimeError {
1359 message: "task.stop() can only be used inside a task".to_string(),
1360 })
1361 }
1362 }
1363 }
1364 }
1365
1366 pub fn value_to_string_for_concat(&mut self, value: &Value) -> Result<Rc<String>> {
1367 match value {
1368 Value::String(s) => Ok(s.clone()),
1369 Value::Struct { name, .. } => self.invoke_tostring(value, name),
1370 Value::Enum { enum_name, .. } => self.invoke_tostring(value, enum_name),
1371 _ => Ok(Rc::new(value.to_string())),
1372 }
1373 }
1374
1375 #[inline(never)]
1376 pub fn call_value(&mut self, func: &Value, args: Vec<Value>) -> Result<Value> {
1377 match func {
1378 Value::Function(func_idx) => {
1379 let mut frame = CallFrame {
1380 function_idx: *func_idx,
1381 ip: 0,
1382 registers: array::from_fn(|_| Value::Nil),
1383 base_register: 0,
1384 return_dest: None,
1385 upvalues: Vec::new(),
1386 };
1387 for (i, arg) in args.into_iter().enumerate() {
1388 frame.registers[i] = arg;
1389 }
1390
1391 let stack_depth_before = self.call_stack.len();
1392 self.call_stack.push(frame);
1393 let previous_target = self.call_until_depth;
1394 self.call_until_depth = Some(stack_depth_before);
1395 let run_result = self.run();
1396 self.call_until_depth = previous_target;
1397 run_result
1398 }
1399
1400 Value::Closure {
1401 function_idx: func_idx,
1402 upvalues,
1403 } => {
1404 let upvalue_values: Vec<Value> = upvalues.iter().map(|uv| uv.get()).collect();
1405 let mut frame = CallFrame {
1406 function_idx: *func_idx,
1407 ip: 0,
1408 registers: array::from_fn(|_| Value::Nil),
1409 base_register: 0,
1410 return_dest: None,
1411 upvalues: upvalue_values,
1412 };
1413 for (i, arg) in args.into_iter().enumerate() {
1414 frame.registers[i] = arg;
1415 }
1416
1417 let stack_depth_before = self.call_stack.len();
1418 self.call_stack.push(frame);
1419 let previous_target = self.call_until_depth;
1420 self.call_until_depth = Some(stack_depth_before);
1421 let run_result = self.run();
1422 self.call_until_depth = previous_target;
1423 run_result
1424 }
1425
1426 Value::NativeFunction(native_fn) => {
1427 self.push_current_vm();
1428 let outcome = native_fn(&args);
1429 self.pop_current_vm();
1430 let outcome = outcome.map_err(|e| LustError::RuntimeError { message: e })?;
1431 match outcome {
1432 NativeCallResult::Return(value) => Ok(value),
1433 NativeCallResult::Yield(_) | NativeCallResult::Stop(_) => {
1434 Err(LustError::RuntimeError {
1435 message: "Yielding or stopping is not allowed from this context"
1436 .to_string(),
1437 })
1438 }
1439 }
1440 }
1441
1442 _ => Err(LustError::RuntimeError {
1443 message: format!("Cannot call non-function value: {:?}", func),
1444 }),
1445 }
1446 }
1447}