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