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