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 _ => Err(LustError::RuntimeError {
431 message: format!("Cannot modulo {:?} and {:?}", l, r),
432 }),
433 })?;
434 }
435
436 Instruction::Neg(dest, src) => {
437 let value = self.get_register(src)?;
438 let result = match value {
439 Value::Int(i) => Value::Int(-i),
440 Value::Float(f) => Value::Float(-f),
441 _ => {
442 return Err(LustError::RuntimeError {
443 message: format!("Cannot negate {:?}", value),
444 })
445 }
446 };
447 self.set_register(dest, result)?;
448 }
449
450 Instruction::Eq(dest, lhs, rhs) => {
451 let left = self.get_register(lhs)?;
452 let right = self.get_register(rhs)?;
453 self.set_register(dest, Value::Bool(left == right))?;
454 }
455
456 Instruction::Ne(dest, lhs, rhs) => {
457 let left = self.get_register(lhs)?;
458 let right = self.get_register(rhs)?;
459 self.set_register(dest, Value::Bool(left != right))?;
460 }
461
462 Instruction::Lt(dest, lhs, rhs) => {
463 self.comparison_op(dest, lhs, rhs, |l, r| l < r)?;
464 }
465
466 Instruction::Le(dest, lhs, rhs) => {
467 self.comparison_op(dest, lhs, rhs, |l, r| l <= r)?;
468 }
469
470 Instruction::Gt(dest, lhs, rhs) => {
471 self.comparison_op(dest, lhs, rhs, |l, r| l > r)?;
472 }
473
474 Instruction::Ge(dest, lhs, rhs) => {
475 self.comparison_op(dest, lhs, rhs, |l, r| l >= r)?;
476 }
477
478 Instruction::And(dest, lhs, rhs) => {
479 let left = self.get_register(lhs)?;
480 let right = self.get_register(rhs)?;
481 let result = Value::Bool(left.is_truthy() && right.is_truthy());
482 self.set_register(dest, result)?;
483 }
484
485 Instruction::Or(dest, lhs, rhs) => {
486 let left = self.get_register(lhs)?;
487 let right = self.get_register(rhs)?;
488 let result = Value::Bool(left.is_truthy() || right.is_truthy());
489 self.set_register(dest, result)?;
490 }
491
492 Instruction::Not(dest, src) => {
493 let value = self.get_register(src)?;
494 self.set_register(dest, Value::Bool(!value.is_truthy()))?;
495 }
496
497 Instruction::Jump(offset) => {
498 let frame = self.call_stack.last_mut().unwrap();
499 frame.ip = (frame.ip as isize + offset as isize) as usize;
500 }
501
502 Instruction::JumpIf(cond, offset) => {
503 let condition = self.get_register(cond)?;
504 if condition.is_truthy() {
505 let frame = self.call_stack.last_mut().unwrap();
506 frame.ip = (frame.ip as isize + offset as isize) as usize;
507 }
508 }
509
510 Instruction::JumpIfNot(cond, offset) => {
511 let condition = self.get_register(cond)?;
512 if !condition.is_truthy() {
513 let frame = self.call_stack.last_mut().unwrap();
514 frame.ip = (frame.ip as isize + offset as isize) as usize;
515 }
516 }
517
518 Instruction::Call(func_reg, first_arg, arg_count, dest_reg) => {
519 let func_value = self.get_register(func_reg)?.clone();
520 match func_value {
521 Value::Function(func_idx) => {
522 let mut args = Vec::new();
523 for i in 0..arg_count {
524 args.push(self.get_register(first_arg + i)?.clone());
525 }
526
527 let mut frame = CallFrame {
528 function_idx: func_idx,
529 ip: 0,
530 registers: array::from_fn(|_| Value::Nil),
531 base_register: 0,
532 return_dest: Some(dest_reg),
533 upvalues: Vec::new(),
534 };
535 for (i, arg) in args.into_iter().enumerate() {
536 frame.registers[i] = arg;
537 }
538
539 self.call_stack.push(frame);
540 }
541
542 Value::Closure {
543 function_idx: func_idx,
544 upvalues,
545 } => {
546 let mut args = Vec::new();
547 for i in 0..arg_count {
548 args.push(self.get_register(first_arg + i)?.clone());
549 }
550
551 let upvalue_values: Vec<Value> =
552 upvalues.iter().map(|uv| uv.get()).collect();
553 let mut frame = CallFrame {
554 function_idx: func_idx,
555 ip: 0,
556 registers: array::from_fn(|_| Value::Nil),
557 base_register: 0,
558 return_dest: Some(dest_reg),
559 upvalues: upvalue_values,
560 };
561 for (i, arg) in args.into_iter().enumerate() {
562 frame.registers[i] = arg;
563 }
564
565 self.call_stack.push(frame);
566 }
567
568 Value::NativeFunction(native_fn) => {
569 let mut args = Vec::new();
570 for i in 0..arg_count {
571 args.push(self.get_register(first_arg + i)?.clone());
572 }
573
574 self.push_current_vm();
575 let outcome = native_fn(&args);
576 self.pop_current_vm();
577 let outcome =
578 outcome.map_err(|e| LustError::RuntimeError { message: e })?;
579 self.handle_native_call_outcome(dest_reg, outcome)?;
580 }
581
582 _ => {
583 return Err(LustError::RuntimeError {
584 message: format!(
585 "Cannot call non-function value: {:?}",
586 func_value
587 ),
588 })
589 }
590 }
591 }
592
593 Instruction::Return(value_reg) => {
594 let return_value = if value_reg == 255 {
595 Value::Nil
596 } else {
597 self.get_register(value_reg)?.clone()
598 };
599 let return_dest = self.call_stack.last().unwrap().return_dest;
600 self.call_stack.pop();
601 if self.call_stack.is_empty() {
602 return Ok(return_value);
603 }
604
605 self.pending_return_value = Some(return_value);
606 self.pending_return_dest = return_dest;
607 }
608
609 Instruction::NewArray(dest, first_elem, count) => {
610 let mut elements = Vec::new();
611 for i in 0..count {
612 elements.push(self.get_register(first_elem + i)?.clone());
613 }
614
615 self.set_register(dest, Value::array(elements))?;
616 }
617
618 Instruction::TupleNew(dest, first_elem, count) => {
619 let mut elements = Vec::new();
620 for offset in 0..(count as usize) {
621 let value = self.get_register(first_elem + offset as u8)?.clone();
622 if let Value::Tuple(existing) = value {
623 elements.extend(existing.iter().cloned());
624 } else {
625 elements.push(value);
626 }
627 }
628
629 self.set_register(dest, Value::tuple(elements))?;
630 }
631
632 Instruction::TupleGet(dest, tuple_reg, index) => {
633 let tuple_value = self.get_register(tuple_reg)?.clone();
634 if let Value::Tuple(values) = tuple_value {
635 let idx = index as usize;
636 if idx >= values.len() {
637 return Err(LustError::RuntimeError {
638 message: format!(
639 "Tuple index {} out of bounds (len {})",
640 idx,
641 values.len()
642 ),
643 });
644 }
645
646 let value = values[idx].clone();
647 self.set_register(dest, value)?;
648 } else {
649 return Err(LustError::RuntimeError {
650 message: "Attempted to destructure non-tuple value".to_string(),
651 });
652 }
653 }
654
655 Instruction::NewMap(dest) => {
656 self.set_register(dest, Value::map(HashMap::new()))?;
657 }
658
659 Instruction::NewStruct(
660 dest,
661 name_idx,
662 first_field_name_idx,
663 first_field,
664 field_count,
665 ) => {
666 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
667 let struct_name = func.chunk.constants[name_idx as usize]
668 .as_string()
669 .ok_or_else(|| LustError::RuntimeError {
670 message: "Struct name must be a string".to_string(),
671 })?
672 .to_string();
673 let mut fields = Vec::with_capacity(field_count as usize);
674 for i in 0..field_count {
675 let field_name = func.chunk.constants
676 [(first_field_name_idx + i as u16) as usize]
677 .as_string_rc()
678 .ok_or_else(|| LustError::RuntimeError {
679 message: "Field name must be a string".to_string(),
680 })?;
681 let value = self.get_register(first_field + i)?.clone();
682 fields.push((field_name, value));
683 }
684
685 let struct_value = self.instantiate_struct(&struct_name, fields)?;
686 self.set_register(dest, struct_value)?;
687 }
688
689 Instruction::NewEnumUnit(dest, enum_name_idx, variant_idx) => {
690 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
691 let enum_name = func.chunk.constants[enum_name_idx as usize]
692 .as_string()
693 .ok_or_else(|| LustError::RuntimeError {
694 message: "Enum name must be a string".to_string(),
695 })?
696 .to_string();
697 let variant_name = func.chunk.constants[variant_idx as usize]
698 .as_string()
699 .ok_or_else(|| LustError::RuntimeError {
700 message: "Variant name must be a string".to_string(),
701 })?
702 .to_string();
703 self.set_register(dest, Value::enum_unit(enum_name, variant_name))?;
704 }
705
706 Instruction::NewEnumVariant(
707 dest,
708 enum_name_idx,
709 variant_idx,
710 first_value,
711 value_count,
712 ) => {
713 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
714 let enum_name = func.chunk.constants[enum_name_idx as usize]
715 .as_string()
716 .ok_or_else(|| LustError::RuntimeError {
717 message: "Enum name must be a string".to_string(),
718 })?
719 .to_string();
720 let variant_name = func.chunk.constants[variant_idx as usize]
721 .as_string()
722 .ok_or_else(|| LustError::RuntimeError {
723 message: "Variant name must be a string".to_string(),
724 })?
725 .to_string();
726 let mut values = Vec::new();
727 for i in 0..value_count {
728 values.push(self.get_register(first_value + i)?.clone());
729 }
730
731 self.set_register(dest, Value::enum_variant(enum_name, variant_name, values))?;
732 }
733
734 Instruction::IsEnumVariant(dest, value_reg, enum_name_idx, variant_idx) => {
735 let value = self.get_register(value_reg)?;
736 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
737 let enum_name = func.chunk.constants[enum_name_idx as usize]
738 .as_string()
739 .ok_or_else(|| LustError::RuntimeError {
740 message: "Enum name must be a string".to_string(),
741 })?;
742 let variant_name = func.chunk.constants[variant_idx as usize]
743 .as_string()
744 .ok_or_else(|| LustError::RuntimeError {
745 message: "Variant name must be a string".to_string(),
746 })?;
747 let is_variant = value.is_enum_variant(enum_name, variant_name);
748 self.set_register(dest, Value::Bool(is_variant))?;
749 }
750
751 Instruction::GetEnumValue(dest, enum_reg, index) => {
752 let enum_value = self.get_register(enum_reg)?;
753 if let Some((_, _, Some(values))) = enum_value.as_enum() {
754 if (index as usize) < values.len() {
755 self.set_register(dest, values[index as usize].clone())?;
756 } else {
757 return Err(LustError::RuntimeError {
758 message: format!(
759 "Enum value index {} out of bounds (has {} values)",
760 index,
761 values.len()
762 ),
763 });
764 }
765 } else {
766 return Err(LustError::RuntimeError {
767 message: "GetEnumValue requires an enum variant with values"
768 .to_string(),
769 });
770 }
771 }
772
773 Instruction::GetField(dest, obj, field_idx) => {
774 let object = self.get_register(obj)?;
775 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
776 let field_name = func.chunk.constants[field_idx as usize]
777 .as_string_rc()
778 .ok_or_else(|| LustError::RuntimeError {
779 message: "Field name must be a string".to_string(),
780 })?;
781 let value = match object {
782 Value::Struct { .. } => object
783 .struct_get_field_rc(&field_name)
784 .unwrap_or(Value::Nil),
785 Value::Map(map) => {
786 use crate::bytecode::ValueKey;
787 let key = ValueKey::String(field_name.clone());
788 map.borrow().get(&key).cloned().unwrap_or(Value::Nil)
789 }
790
791 _ => {
792 return Err(LustError::RuntimeError {
793 message: format!(
794 "Cannot get field '{}' from {:?}",
795 field_name.as_str(),
796 object
797 ),
798 })
799 }
800 };
801 self.set_register(dest, value)?;
802 }
803
804 Instruction::SetField(obj_reg, field_idx, value_reg) => {
805 let object = self.get_register(obj_reg)?;
806 let value = self.get_register(value_reg)?.clone();
807 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
808 let field_name = func.chunk.constants[field_idx as usize]
809 .as_string_rc()
810 .ok_or_else(|| LustError::RuntimeError {
811 message: "Field name must be a string".to_string(),
812 })?;
813 let mut invalidate_key: Option<usize> = None;
814 match object {
815 Value::Struct { .. } => {
816 invalidate_key = Self::struct_cache_key(object);
817 object
818 .struct_set_field_rc(&field_name, value)
819 .map_err(|message| LustError::RuntimeError { message })?;
820 }
821
822 Value::Map(map) => {
823 use crate::bytecode::ValueKey;
824 let key = ValueKey::String(field_name.clone());
825 map.borrow_mut().insert(key, value);
826 }
827
828 _ => {
829 return Err(LustError::RuntimeError {
830 message: format!(
831 "Cannot set field '{}' on {:?}",
832 field_name.as_str(),
833 object
834 ),
835 })
836 }
837 }
838
839 if let Some(key) = invalidate_key {
840 self.struct_tostring_cache.remove(&key);
841 }
842 }
843
844 Instruction::Concat(dest, lhs, rhs) => {
845 let (left, right) = {
846 let frame =
847 self.call_stack
848 .last_mut()
849 .ok_or_else(|| LustError::RuntimeError {
850 message: "Empty call stack".to_string(),
851 })?;
852 let left = frame.registers[lhs as usize].clone();
853 let right = frame.registers[rhs as usize].clone();
854 (left, right)
855 };
856 let left_str = self.value_to_string_for_concat(&left)?;
857 let right_str = self.value_to_string_for_concat(&right)?;
858 let mut combined = String::with_capacity(left_str.len() + right_str.len());
859 combined.push_str(left_str.as_ref());
860 combined.push_str(right_str.as_ref());
861 let result = Value::string(combined);
862 self.set_register(dest, result)?;
863 }
864
865 Instruction::GetIndex(dest, array_reg, index_reg) => {
866 let collection = self.get_register(array_reg)?;
867 let index = self.get_register(index_reg)?;
868 let result = match collection {
869 Value::Array(arr) => {
870 let idx = index.as_int().ok_or_else(|| LustError::RuntimeError {
871 message: "Array index must be an integer".to_string(),
872 })?;
873 let borrowed = arr.borrow();
874 if idx < 0 || idx as usize >= borrowed.len() {
875 return Err(LustError::RuntimeError {
876 message: format!(
877 "Array index {} out of bounds (length: {})",
878 idx,
879 borrowed.len()
880 ),
881 });
882 }
883
884 borrowed[idx as usize].clone()
885 }
886
887 Value::Map(map) => {
888 use crate::bytecode::ValueKey;
889 let key = ValueKey::from_value(index).ok_or_else(|| {
890 LustError::RuntimeError {
891 message: format!(
892 "Cannot use {:?} as map key (not hashable)",
893 index
894 ),
895 }
896 })?;
897 map.borrow().get(&key).cloned().unwrap_or(Value::Nil)
898 }
899
900 _ => {
901 return Err(LustError::RuntimeError {
902 message: format!("Cannot index {:?}", collection.type_of()),
903 })
904 }
905 };
906 self.set_register(dest, result)?;
907 }
908
909 Instruction::ArrayLen(dest, array_reg) => {
910 let collection = self.get_register(array_reg)?;
911 match collection {
912 Value::Array(arr) => {
913 let len = int_from_usize(arr.borrow().len());
914 self.set_register(dest, Value::Int(len))?;
915 }
916
917 _ => {
918 return Err(LustError::RuntimeError {
919 message: format!(
920 "ArrayLen requires array, got {:?}",
921 collection.type_of()
922 ),
923 });
924 }
925 }
926 }
927
928 Instruction::CallMethod(
929 obj_reg,
930 method_name_idx,
931 first_arg,
932 arg_count,
933 dest_reg,
934 ) => {
935 let object = self.get_register(obj_reg)?.clone();
936 let method_name = {
937 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
938 func.chunk.constants[method_name_idx as usize]
939 .as_string()
940 .ok_or_else(|| LustError::RuntimeError {
941 message: "Method name must be a string".to_string(),
942 })?
943 .to_string()
944 };
945 if let Value::Struct {
946 name: struct_name, ..
947 } = &object
948 {
949 let mangled_name = format!("{}:{}", struct_name, method_name);
950 if let Some(func_idx) =
951 self.functions.iter().position(|f| f.name == mangled_name)
952 {
953 let mut frame = CallFrame {
954 function_idx: func_idx,
955 ip: 0,
956 registers: array::from_fn(|_| Value::Nil),
957 base_register: 0,
958 return_dest: Some(dest_reg),
959 upvalues: Vec::new(),
960 };
961 frame.registers[0] = object.clone();
962 for i in 0..arg_count {
963 frame.registers[(i + 1) as usize] =
964 self.get_register(first_arg + i)?.clone();
965 }
966
967 self.call_stack.push(frame);
968 continue;
969 }
970 }
971
972 let mut args = Vec::new();
973 for i in 0..arg_count {
974 args.push(self.get_register(first_arg + i)?.clone());
975 }
976
977 let result = self.call_builtin_method(&object, &method_name, args)?;
978 self.set_register(dest_reg, result)?;
979 }
980
981 Instruction::Closure(dest, func_idx, first_upvalue_reg, upvalue_count) => {
982 use crate::bytecode::Upvalue;
983 let mut upvalues = Vec::new();
984 for i in 0..upvalue_count {
985 let value = self.get_register(first_upvalue_reg + i)?.clone();
986 upvalues.push(Upvalue::new(value));
987 }
988
989 let closure = Value::Closure {
990 function_idx: func_idx as usize,
991 upvalues: Rc::new(upvalues),
992 };
993 self.set_register(dest, closure)?;
994 }
995
996 Instruction::LoadUpvalue(dest, upvalue_idx) => {
997 let frame = self
998 .call_stack
999 .last()
1000 .ok_or_else(|| LustError::RuntimeError {
1001 message: "Empty call stack".to_string(),
1002 })?;
1003 if (upvalue_idx as usize) < frame.upvalues.len() {
1004 let value = frame.upvalues[upvalue_idx as usize].clone();
1005 self.set_register(dest, value)?;
1006 } else {
1007 return Err(LustError::RuntimeError {
1008 message: format!(
1009 "Upvalue index {} out of bounds (have {} upvalues)",
1010 upvalue_idx,
1011 frame.upvalues.len()
1012 ),
1013 });
1014 }
1015 }
1016
1017 Instruction::StoreUpvalue(upvalue_idx, src) => {
1018 let value = self.get_register(src)?.clone();
1019 let frame =
1020 self.call_stack
1021 .last_mut()
1022 .ok_or_else(|| LustError::RuntimeError {
1023 message: "Empty call stack".to_string(),
1024 })?;
1025 if (upvalue_idx as usize) < frame.upvalues.len() {
1026 frame.upvalues[upvalue_idx as usize] = value;
1027 } else {
1028 return Err(LustError::RuntimeError {
1029 message: format!(
1030 "Upvalue index {} out of bounds (have {} upvalues)",
1031 upvalue_idx,
1032 frame.upvalues.len()
1033 ),
1034 });
1035 }
1036 }
1037
1038 Instruction::SetIndex(collection_reg, index_reg, value_reg) => {
1039 let collection = self.get_register(collection_reg)?;
1040 let index = self.get_register(index_reg)?;
1041 let value = self.get_register(value_reg)?.clone();
1042 match collection {
1043 Value::Array(arr) => {
1044 let idx = index.as_int().ok_or_else(|| LustError::RuntimeError {
1045 message: "Array index must be an integer".to_string(),
1046 })?;
1047 let mut borrowed = arr.borrow_mut();
1048 if idx < 0 || idx as usize >= borrowed.len() {
1049 return Err(LustError::RuntimeError {
1050 message: format!(
1051 "Array index {} out of bounds (length: {})",
1052 idx,
1053 borrowed.len()
1054 ),
1055 });
1056 }
1057
1058 borrowed[idx as usize] = value;
1059 }
1060
1061 Value::Map(map) => {
1062 use crate::bytecode::ValueKey;
1063 let key = ValueKey::from_value(index).ok_or_else(|| {
1064 LustError::RuntimeError {
1065 message: format!(
1066 "Cannot use {:?} as map key (not hashable)",
1067 index
1068 ),
1069 }
1070 })?;
1071 map.borrow_mut().insert(key, value);
1072 }
1073
1074 _ => {
1075 return Err(LustError::RuntimeError {
1076 message: format!("Cannot index {:?}", collection.type_of()),
1077 })
1078 }
1079 }
1080 }
1081
1082 Instruction::TypeIs(dest, value_reg, type_name_idx) => {
1083 let value = self.get_register(value_reg)?.clone();
1084 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
1085 let type_name = func.chunk.constants[type_name_idx as usize]
1086 .as_string()
1087 .ok_or_else(|| LustError::RuntimeError {
1088 message: "Type name must be a string".to_string(),
1089 })?
1090 .to_string();
1091 let matches = self.value_is_type(&value, &type_name);
1092 self.set_register(dest, Value::Bool(matches))?;
1093 }
1094 }
1095
1096 if self.jit.enabled {
1097 if let Some(recorder) = &mut self.trace_recorder {
1098 if recorder.is_recording() {
1099 if self.skip_next_trace_record {
1100 self.skip_next_trace_record = false;
1101 } else {
1102 let function = &self.functions[func_idx];
1103 if let Some(frame) = self.call_stack.last() {
1104 if let Err(e) = recorder.record_instruction(
1105 instruction,
1106 ip_before_execution,
1107 &frame.registers,
1108 function,
1109 func_idx,
1110 ) {
1111 crate::jit::log(|| format!("⚠️ JIT: {}", e));
1112 self.trace_recorder = None;
1113 }
1114 }
1115 }
1116 }
1117 }
1118 }
1119 }
1120 }
1121
1122 pub(super) fn binary_op<F>(
1123 &mut self,
1124 dest: Register,
1125 lhs: Register,
1126 rhs: Register,
1127 op: F,
1128 ) -> Result<()>
1129 where
1130 F: FnOnce(&Value, &Value) -> Result<Value>,
1131 {
1132 let left = self.get_register(lhs)?;
1133 let right = self.get_register(rhs)?;
1134 let result = op(left, right)?;
1135 self.set_register(dest, result)
1136 }
1137
1138 pub(super) fn comparison_op<F>(
1139 &mut self,
1140 dest: Register,
1141 lhs: Register,
1142 rhs: Register,
1143 op: F,
1144 ) -> Result<()>
1145 where
1146 F: FnOnce(LustFloat, LustFloat) -> bool,
1147 {
1148 let left = self.get_register(lhs)?;
1149 let right = self.get_register(rhs)?;
1150 let result = match (left, right) {
1151 (Value::Int(a), Value::Int(b)) => op(float_from_int(*a), float_from_int(*b)),
1152 (Value::Float(a), Value::Float(b)) => op(*a, *b),
1153 (Value::Int(a), Value::Float(b)) => op(float_from_int(*a), *b),
1154 (Value::Float(a), Value::Int(b)) => op(*a, float_from_int(*b)),
1155 _ => {
1156 return Err(LustError::RuntimeError {
1157 message: format!("Cannot compare {:?} and {:?}", left, right),
1158 })
1159 }
1160 };
1161 self.set_register(dest, Value::Bool(result))
1162 }
1163
1164 pub(super) fn value_is_type(&self, value: &Value, type_name: &str) -> bool {
1165 let value_type_name = match value {
1166 Value::Int(_) => "int",
1167 Value::Float(_) => "float",
1168 Value::String(_) => "string",
1169 Value::Bool(_) => "bool",
1170 Value::Nil => "nil",
1171 Value::Array(_) => "Array",
1172 Value::Tuple(_) => "Tuple",
1173 Value::Map(_) => "Map",
1174 Value::Struct { name, .. } => name.as_str(),
1175 Value::WeakStruct(weak) => weak.struct_name(),
1176 Value::Enum { enum_name, .. } => enum_name.as_str(),
1177 Value::Function(_) | Value::NativeFunction(_) | Value::Closure { .. } => "function",
1178 Value::Iterator(_) => "Iterator",
1179 Value::Task(_) => "task",
1180 };
1181 if value_type_name == type_name {
1182 return true;
1183 }
1184
1185 if type_name.starts_with("Array") && matches!(value, Value::Array(_)) {
1186 return true;
1187 }
1188
1189 if type_name.starts_with("Map") && matches!(value, Value::Map(_)) {
1190 return true;
1191 }
1192
1193 if type_name.starts_with("Tuple") && matches!(value, Value::Tuple(_)) {
1194 return true;
1195 }
1196
1197 if type_name == "Option"
1198 && matches!(value, Value::Enum { enum_name, .. } if enum_name == "Option")
1199 {
1200 return true;
1201 }
1202
1203 if type_name == "Result"
1204 && matches!(value, Value::Enum { enum_name, .. } if enum_name == "Result")
1205 {
1206 return true;
1207 }
1208
1209 if type_name == "unknown" {
1210 return true;
1211 }
1212
1213 if let Some(_) = self
1214 .trait_impls
1215 .get(&(value_type_name.to_string(), type_name.to_string()))
1216 {
1217 return true;
1218 }
1219
1220 false
1221 }
1222
1223 pub(super) fn get_register(&self, reg: Register) -> Result<&Value> {
1224 let frame = self
1225 .call_stack
1226 .last()
1227 .ok_or_else(|| LustError::RuntimeError {
1228 message: "Empty call stack".to_string(),
1229 })?;
1230 Ok(&frame.registers[reg as usize])
1231 }
1232
1233 pub(super) fn set_register(&mut self, reg: Register, value: Value) -> Result<()> {
1234 self.observe_value(&value);
1235 let frame = self
1236 .call_stack
1237 .last_mut()
1238 .ok_or_else(|| LustError::RuntimeError {
1239 message: "Empty call stack".to_string(),
1240 })?;
1241 frame.registers[reg as usize] = value;
1242 self.maybe_collect_cycles();
1243 Ok(())
1244 }
1245
1246 pub(super) fn handle_native_call_outcome(
1247 &mut self,
1248 dest: Register,
1249 outcome: NativeCallResult,
1250 ) -> Result<()> {
1251 match outcome {
1252 NativeCallResult::Return(value) => self.set_register(dest, value),
1253 NativeCallResult::Yield(value) => {
1254 if self.current_task.is_some() {
1255 self.set_register(dest, Value::Nil)?;
1256 self.pending_task_signal = Some(TaskSignal::Yield { dest, value });
1257 Ok(())
1258 } else {
1259 Err(LustError::RuntimeError {
1260 message: "task.yield() can only be used inside a task".to_string(),
1261 })
1262 }
1263 }
1264
1265 NativeCallResult::Stop(value) => {
1266 if self.current_task.is_some() {
1267 self.set_register(dest, Value::Nil)?;
1268 self.pending_task_signal = Some(TaskSignal::Stop { value });
1269 Ok(())
1270 } else {
1271 Err(LustError::RuntimeError {
1272 message: "task.stop() can only be used inside a task".to_string(),
1273 })
1274 }
1275 }
1276 }
1277 }
1278
1279 pub fn value_to_string_for_concat(&mut self, value: &Value) -> Result<Rc<String>> {
1280 match value {
1281 Value::String(s) => Ok(s.clone()),
1282 Value::Struct { name, .. } => self.invoke_tostring(value, name),
1283 Value::Enum { enum_name, .. } => self.invoke_tostring(value, enum_name),
1284 _ => Ok(Rc::new(value.to_string())),
1285 }
1286 }
1287
1288 pub fn call_value(&mut self, func: &Value, args: Vec<Value>) -> Result<Value> {
1289 match func {
1290 Value::Function(func_idx) => {
1291 let mut frame = CallFrame {
1292 function_idx: *func_idx,
1293 ip: 0,
1294 registers: array::from_fn(|_| Value::Nil),
1295 base_register: 0,
1296 return_dest: None,
1297 upvalues: Vec::new(),
1298 };
1299 for (i, arg) in args.into_iter().enumerate() {
1300 frame.registers[i] = arg;
1301 }
1302
1303 let stack_depth_before = self.call_stack.len();
1304 self.call_stack.push(frame);
1305 let previous_target = self.call_until_depth;
1306 self.call_until_depth = Some(stack_depth_before);
1307 let run_result = self.run();
1308 self.call_until_depth = previous_target;
1309 run_result
1310 }
1311
1312 Value::Closure {
1313 function_idx: func_idx,
1314 upvalues,
1315 } => {
1316 let upvalue_values: Vec<Value> = upvalues.iter().map(|uv| uv.get()).collect();
1317 let mut frame = CallFrame {
1318 function_idx: *func_idx,
1319 ip: 0,
1320 registers: array::from_fn(|_| Value::Nil),
1321 base_register: 0,
1322 return_dest: None,
1323 upvalues: upvalue_values,
1324 };
1325 for (i, arg) in args.into_iter().enumerate() {
1326 frame.registers[i] = arg;
1327 }
1328
1329 let stack_depth_before = self.call_stack.len();
1330 self.call_stack.push(frame);
1331 let previous_target = self.call_until_depth;
1332 self.call_until_depth = Some(stack_depth_before);
1333 let run_result = self.run();
1334 self.call_until_depth = previous_target;
1335 run_result
1336 }
1337
1338 Value::NativeFunction(native_fn) => {
1339 self.push_current_vm();
1340 let outcome = native_fn(&args);
1341 self.pop_current_vm();
1342 let outcome = outcome.map_err(|e| LustError::RuntimeError { message: e })?;
1343 match outcome {
1344 NativeCallResult::Return(value) => Ok(value),
1345 NativeCallResult::Yield(_) | NativeCallResult::Stop(_) => {
1346 Err(LustError::RuntimeError {
1347 message: "Yielding or stopping is not allowed from this context"
1348 .to_string(),
1349 })
1350 }
1351 }
1352 }
1353
1354 _ => Err(LustError::RuntimeError {
1355 message: format!("Cannot call non-function value: {:?}", func),
1356 }),
1357 }
1358 }
1359}