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::NewTable(dest) => {
660 self.set_register(dest, Value::table(HashMap::new()))?;
661 }
662
663 Instruction::NewStruct(
664 dest,
665 name_idx,
666 first_field_name_idx,
667 first_field,
668 field_count,
669 ) => {
670 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
671 let struct_name = func.chunk.constants[name_idx as usize]
672 .as_string()
673 .ok_or_else(|| LustError::RuntimeError {
674 message: "Struct name must be a string".to_string(),
675 })?
676 .to_string();
677 let mut fields = Vec::with_capacity(field_count as usize);
678 for i in 0..field_count {
679 let field_name = func.chunk.constants
680 [(first_field_name_idx + i as u16) as usize]
681 .as_string_rc()
682 .ok_or_else(|| LustError::RuntimeError {
683 message: "Field name must be a string".to_string(),
684 })?;
685 let value = self.get_register(first_field + i)?.clone();
686 fields.push((field_name, value));
687 }
688
689 let struct_value = self.instantiate_struct(&struct_name, fields)?;
690 self.set_register(dest, struct_value)?;
691 }
692
693 Instruction::NewEnumUnit(dest, enum_name_idx, variant_idx) => {
694 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
695 let enum_name = func.chunk.constants[enum_name_idx as usize]
696 .as_string()
697 .ok_or_else(|| LustError::RuntimeError {
698 message: "Enum name must be a string".to_string(),
699 })?
700 .to_string();
701 let variant_name = func.chunk.constants[variant_idx as usize]
702 .as_string()
703 .ok_or_else(|| LustError::RuntimeError {
704 message: "Variant name must be a string".to_string(),
705 })?
706 .to_string();
707 self.set_register(dest, Value::enum_unit(enum_name, variant_name))?;
708 }
709
710 Instruction::NewEnumVariant(
711 dest,
712 enum_name_idx,
713 variant_idx,
714 first_value,
715 value_count,
716 ) => {
717 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
718 let enum_name = func.chunk.constants[enum_name_idx as usize]
719 .as_string()
720 .ok_or_else(|| LustError::RuntimeError {
721 message: "Enum name must be a string".to_string(),
722 })?
723 .to_string();
724 let variant_name = func.chunk.constants[variant_idx as usize]
725 .as_string()
726 .ok_or_else(|| LustError::RuntimeError {
727 message: "Variant name must be a string".to_string(),
728 })?
729 .to_string();
730 let mut values = Vec::new();
731 for i in 0..value_count {
732 values.push(self.get_register(first_value + i)?.clone());
733 }
734
735 self.set_register(dest, Value::enum_variant(enum_name, variant_name, values))?;
736 }
737
738 Instruction::IsEnumVariant(dest, value_reg, enum_name_idx, variant_idx) => {
739 let value = self.get_register(value_reg)?;
740 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
741 let enum_name = func.chunk.constants[enum_name_idx as usize]
742 .as_string()
743 .ok_or_else(|| LustError::RuntimeError {
744 message: "Enum name must be a string".to_string(),
745 })?;
746 let variant_name = func.chunk.constants[variant_idx as usize]
747 .as_string()
748 .ok_or_else(|| LustError::RuntimeError {
749 message: "Variant name must be a string".to_string(),
750 })?;
751 let is_variant = value.is_enum_variant(enum_name, variant_name);
752 self.set_register(dest, Value::Bool(is_variant))?;
753 }
754
755 Instruction::GetEnumValue(dest, enum_reg, index) => {
756 let enum_value = self.get_register(enum_reg)?;
757 if let Some((_, _, Some(values))) = enum_value.as_enum() {
758 if (index as usize) < values.len() {
759 self.set_register(dest, values[index as usize].clone())?;
760 } else {
761 return Err(LustError::RuntimeError {
762 message: format!(
763 "Enum value index {} out of bounds (has {} values)",
764 index,
765 values.len()
766 ),
767 });
768 }
769 } else {
770 return Err(LustError::RuntimeError {
771 message: "GetEnumValue requires an enum variant with values"
772 .to_string(),
773 });
774 }
775 }
776
777 Instruction::GetField(dest, obj, field_idx) => {
778 let object = self.get_register(obj)?;
779 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
780 let field_name = func.chunk.constants[field_idx as usize]
781 .as_string_rc()
782 .ok_or_else(|| LustError::RuntimeError {
783 message: "Field name must be a string".to_string(),
784 })?;
785 let value = match object {
786 Value::Struct { .. } => object
787 .struct_get_field_rc(&field_name)
788 .unwrap_or(Value::Nil),
789 Value::Map(map) => {
790 use crate::bytecode::ValueKey;
791 let key = ValueKey::String(field_name.clone());
792 map.borrow().get(&key).cloned().unwrap_or(Value::Nil)
793 }
794
795 Value::Table(table) => {
796 use crate::bytecode::ValueKey;
797 let key = ValueKey::String(field_name.clone());
798 table.borrow().get(&key).cloned().unwrap_or(Value::Nil)
799 }
800
801 _ => {
802 return Err(LustError::RuntimeError {
803 message: format!(
804 "Cannot get field '{}' from {:?}",
805 field_name.as_str(),
806 object
807 ),
808 })
809 }
810 };
811 self.set_register(dest, value)?;
812 }
813
814 Instruction::SetField(obj_reg, field_idx, value_reg) => {
815 let object = self.get_register(obj_reg)?;
816 let value = self.get_register(value_reg)?.clone();
817 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
818 let field_name = func.chunk.constants[field_idx as usize]
819 .as_string_rc()
820 .ok_or_else(|| LustError::RuntimeError {
821 message: "Field name must be a string".to_string(),
822 })?;
823 let mut invalidate_key: Option<usize> = None;
824 match object {
825 Value::Struct { .. } => {
826 invalidate_key = Self::struct_cache_key(object);
827 object
828 .struct_set_field_rc(&field_name, value)
829 .map_err(|message| LustError::RuntimeError { message })?;
830 }
831
832 Value::Map(map) => {
833 use crate::bytecode::ValueKey;
834 let key = ValueKey::String(field_name.clone());
835 map.borrow_mut().insert(key, value);
836 }
837
838 _ => {
839 return Err(LustError::RuntimeError {
840 message: format!(
841 "Cannot set field '{}' on {:?}",
842 field_name.as_str(),
843 object
844 ),
845 })
846 }
847 }
848
849 if let Some(key) = invalidate_key {
850 self.struct_tostring_cache.remove(&key);
851 }
852 }
853
854 Instruction::Concat(dest, lhs, rhs) => {
855 let (left, right) = {
856 let frame =
857 self.call_stack
858 .last_mut()
859 .ok_or_else(|| LustError::RuntimeError {
860 message: "Empty call stack".to_string(),
861 })?;
862 let left = frame.registers[lhs as usize].clone();
863 let right = frame.registers[rhs as usize].clone();
864 (left, right)
865 };
866 let left_str = self.value_to_string_for_concat(&left)?;
867 let right_str = self.value_to_string_for_concat(&right)?;
868 let mut combined = String::with_capacity(left_str.len() + right_str.len());
869 combined.push_str(left_str.as_ref());
870 combined.push_str(right_str.as_ref());
871 let result = Value::string(combined);
872 self.set_register(dest, result)?;
873 }
874
875 Instruction::GetIndex(dest, array_reg, index_reg) => {
876 let collection = self.get_register(array_reg)?;
877 let index = self.get_register(index_reg)?;
878 let result = match collection {
879 Value::Array(arr) => {
880 let idx = index.as_int().ok_or_else(|| LustError::RuntimeError {
881 message: "Array index must be an integer".to_string(),
882 })?;
883 let borrowed = arr.borrow();
884 if idx < 0 || idx as usize >= borrowed.len() {
885 return Err(LustError::RuntimeError {
886 message: format!(
887 "Array index {} out of bounds (length: {})",
888 idx,
889 borrowed.len()
890 ),
891 });
892 }
893
894 borrowed[idx as usize].clone()
895 }
896
897 Value::Map(map) => {
898 use crate::bytecode::ValueKey;
899 let key = ValueKey::from_value(index).ok_or_else(|| {
900 LustError::RuntimeError {
901 message: format!(
902 "Cannot use {:?} as map key (not hashable)",
903 index
904 ),
905 }
906 })?;
907 map.borrow().get(&key).cloned().unwrap_or(Value::Nil)
908 }
909
910 Value::Table(table) => {
911 use crate::bytecode::ValueKey;
912 let key = ValueKey::from_value(index).ok_or_else(|| {
913 LustError::RuntimeError {
914 message: format!(
915 "Cannot use {:?} as table key (not hashable)",
916 index
917 ),
918 }
919 })?;
920 table.borrow().get(&key).cloned().unwrap_or(Value::Nil)
921 }
922
923 _ => {
924 return Err(LustError::RuntimeError {
925 message: format!("Cannot index {:?}", collection.type_of()),
926 })
927 }
928 };
929 self.set_register(dest, result)?;
930 }
931
932 Instruction::ArrayLen(dest, array_reg) => {
933 let collection = self.get_register(array_reg)?;
934 match collection {
935 Value::Array(arr) => {
936 let len = int_from_usize(arr.borrow().len());
937 self.set_register(dest, Value::Int(len))?;
938 }
939
940 _ => {
941 return Err(LustError::RuntimeError {
942 message: format!(
943 "ArrayLen requires array, got {:?}",
944 collection.type_of()
945 ),
946 });
947 }
948 }
949 }
950
951 Instruction::CallMethod(
952 obj_reg,
953 method_name_idx,
954 first_arg,
955 arg_count,
956 dest_reg,
957 ) => {
958 let object = self.get_register(obj_reg)?.clone();
959 let method_name = {
960 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
961 func.chunk.constants[method_name_idx as usize]
962 .as_string()
963 .ok_or_else(|| LustError::RuntimeError {
964 message: "Method name must be a string".to_string(),
965 })?
966 .to_string()
967 };
968 if let Value::Struct {
969 name: struct_name, ..
970 } = &object
971 {
972 let mangled_name = format!("{}:{}", struct_name, method_name);
973 if let Some(func_idx) =
974 self.functions.iter().position(|f| f.name == mangled_name)
975 {
976 let mut frame = CallFrame {
977 function_idx: func_idx,
978 ip: 0,
979 registers: array::from_fn(|_| Value::Nil),
980 base_register: 0,
981 return_dest: Some(dest_reg),
982 upvalues: Vec::new(),
983 };
984 frame.registers[0] = object.clone();
985 for i in 0..arg_count {
986 frame.registers[(i + 1) as usize] =
987 self.get_register(first_arg + i)?.clone();
988 }
989
990 self.call_stack.push(frame);
991 continue;
992 }
993 }
994
995 let mut args = Vec::new();
996 for i in 0..arg_count {
997 args.push(self.get_register(first_arg + i)?.clone());
998 }
999
1000 let result = self.call_builtin_method(&object, &method_name, args)?;
1001 self.set_register(dest_reg, result)?;
1002 }
1003
1004 Instruction::Closure(dest, func_idx, first_upvalue_reg, upvalue_count) => {
1005 use crate::bytecode::Upvalue;
1006 let mut upvalues = Vec::new();
1007 for i in 0..upvalue_count {
1008 let value = self.get_register(first_upvalue_reg + i)?.clone();
1009 upvalues.push(Upvalue::new(value));
1010 }
1011
1012 let closure = Value::Closure {
1013 function_idx: func_idx as usize,
1014 upvalues: Rc::new(upvalues),
1015 };
1016 self.set_register(dest, closure)?;
1017 }
1018
1019 Instruction::LoadUpvalue(dest, upvalue_idx) => {
1020 let frame = self
1021 .call_stack
1022 .last()
1023 .ok_or_else(|| LustError::RuntimeError {
1024 message: "Empty call stack".to_string(),
1025 })?;
1026 if (upvalue_idx as usize) < frame.upvalues.len() {
1027 let value = frame.upvalues[upvalue_idx as usize].clone();
1028 self.set_register(dest, value)?;
1029 } else {
1030 return Err(LustError::RuntimeError {
1031 message: format!(
1032 "Upvalue index {} out of bounds (have {} upvalues)",
1033 upvalue_idx,
1034 frame.upvalues.len()
1035 ),
1036 });
1037 }
1038 }
1039
1040 Instruction::StoreUpvalue(upvalue_idx, src) => {
1041 let value = self.get_register(src)?.clone();
1042 let frame =
1043 self.call_stack
1044 .last_mut()
1045 .ok_or_else(|| LustError::RuntimeError {
1046 message: "Empty call stack".to_string(),
1047 })?;
1048 if (upvalue_idx as usize) < frame.upvalues.len() {
1049 frame.upvalues[upvalue_idx as usize] = value;
1050 } else {
1051 return Err(LustError::RuntimeError {
1052 message: format!(
1053 "Upvalue index {} out of bounds (have {} upvalues)",
1054 upvalue_idx,
1055 frame.upvalues.len()
1056 ),
1057 });
1058 }
1059 }
1060
1061 Instruction::SetIndex(collection_reg, index_reg, value_reg) => {
1062 let collection = self.get_register(collection_reg)?;
1063 let index = self.get_register(index_reg)?;
1064 let value = self.get_register(value_reg)?.clone();
1065 match collection {
1066 Value::Array(arr) => {
1067 let idx = index.as_int().ok_or_else(|| LustError::RuntimeError {
1068 message: "Array index must be an integer".to_string(),
1069 })?;
1070 let mut borrowed = arr.borrow_mut();
1071 if idx < 0 || idx as usize >= borrowed.len() {
1072 return Err(LustError::RuntimeError {
1073 message: format!(
1074 "Array index {} out of bounds (length: {})",
1075 idx,
1076 borrowed.len()
1077 ),
1078 });
1079 }
1080
1081 borrowed[idx as usize] = value;
1082 }
1083
1084 Value::Map(map) => {
1085 use crate::bytecode::ValueKey;
1086 let key = ValueKey::from_value(index).ok_or_else(|| {
1087 LustError::RuntimeError {
1088 message: format!(
1089 "Cannot use {:?} as map key (not hashable)",
1090 index
1091 ),
1092 }
1093 })?;
1094 map.borrow_mut().insert(key, value);
1095 }
1096
1097 Value::Table(table) => {
1098 use crate::bytecode::ValueKey;
1099 let key = ValueKey::from_value(index).ok_or_else(|| {
1100 LustError::RuntimeError {
1101 message: format!(
1102 "Cannot use {:?} as table key (not hashable)",
1103 index
1104 ),
1105 }
1106 })?;
1107 table.borrow_mut().insert(key, value);
1108 }
1109
1110 _ => {
1111 return Err(LustError::RuntimeError {
1112 message: format!("Cannot index {:?}", collection.type_of()),
1113 })
1114 }
1115 }
1116 }
1117
1118 Instruction::TypeIs(dest, value_reg, type_name_idx) => {
1119 let value = self.get_register(value_reg)?.clone();
1120 let func = &self.functions[self.call_stack.last().unwrap().function_idx];
1121 let type_name = func.chunk.constants[type_name_idx as usize]
1122 .as_string()
1123 .ok_or_else(|| LustError::RuntimeError {
1124 message: "Type name must be a string".to_string(),
1125 })?
1126 .to_string();
1127 let matches = self.value_is_type(&value, &type_name);
1128 self.set_register(dest, Value::Bool(matches))?;
1129 }
1130 }
1131
1132 if self.jit.enabled {
1133 if let Some(recorder) = &mut self.trace_recorder {
1134 if recorder.is_recording() {
1135 if self.skip_next_trace_record {
1136 self.skip_next_trace_record = false;
1137 } else {
1138 let function = &self.functions[func_idx];
1139 if let Some(frame) = self.call_stack.last() {
1140 if let Err(e) = recorder.record_instruction(
1141 instruction,
1142 ip_before_execution,
1143 &frame.registers,
1144 function,
1145 func_idx,
1146 ) {
1147 crate::jit::log(|| format!("⚠️ JIT: {}", e));
1148 self.trace_recorder = None;
1149 }
1150 }
1151 }
1152 }
1153 }
1154 }
1155 }
1156 }
1157
1158 pub(super) fn binary_op<F>(
1159 &mut self,
1160 dest: Register,
1161 lhs: Register,
1162 rhs: Register,
1163 op: F,
1164 ) -> Result<()>
1165 where
1166 F: FnOnce(&Value, &Value) -> Result<Value>,
1167 {
1168 let left = self.get_register(lhs)?;
1169 let right = self.get_register(rhs)?;
1170 let result = op(left, right)?;
1171 self.set_register(dest, result)
1172 }
1173
1174 pub(super) fn comparison_op<F>(
1175 &mut self,
1176 dest: Register,
1177 lhs: Register,
1178 rhs: Register,
1179 op: F,
1180 ) -> Result<()>
1181 where
1182 F: FnOnce(LustFloat, LustFloat) -> bool,
1183 {
1184 let left = self.get_register(lhs)?;
1185 let right = self.get_register(rhs)?;
1186 let result = match (left, right) {
1187 (Value::Int(a), Value::Int(b)) => op(float_from_int(*a), float_from_int(*b)),
1188 (Value::Float(a), Value::Float(b)) => op(*a, *b),
1189 (Value::Int(a), Value::Float(b)) => op(float_from_int(*a), *b),
1190 (Value::Float(a), Value::Int(b)) => op(*a, float_from_int(*b)),
1191 _ => {
1192 return Err(LustError::RuntimeError {
1193 message: format!("Cannot compare {:?} and {:?}", left, right),
1194 })
1195 }
1196 };
1197 self.set_register(dest, Value::Bool(result))
1198 }
1199
1200 pub(super) fn value_is_type(&self, value: &Value, type_name: &str) -> bool {
1201 let value_type_name = match value {
1202 Value::Int(_) => "int",
1203 Value::Float(_) => "float",
1204 Value::String(_) => "string",
1205 Value::Bool(_) => "bool",
1206 Value::Nil => "nil",
1207 Value::Array(_) => "Array",
1208 Value::Tuple(_) => "Tuple",
1209 Value::Map(_) => "Map",
1210 Value::Table(_) => "Table",
1211 Value::Struct { name, .. } => name.as_str(),
1212 Value::WeakStruct(weak) => weak.struct_name(),
1213 Value::Enum { enum_name, .. } => enum_name.as_str(),
1214 Value::Function(_) | Value::NativeFunction(_) | Value::Closure { .. } => "function",
1215 Value::Iterator(_) => "Iterator",
1216 Value::Task(_) => "task",
1217 };
1218 if value_type_name == type_name {
1219 return true;
1220 }
1221
1222 if type_name.starts_with("Array") && matches!(value, Value::Array(_)) {
1223 return true;
1224 }
1225
1226 if type_name.starts_with("Map") && matches!(value, Value::Map(_)) {
1227 return true;
1228 }
1229
1230 if type_name.starts_with("Tuple") && matches!(value, Value::Tuple(_)) {
1231 return true;
1232 }
1233
1234 if type_name == "Option"
1235 && matches!(value, Value::Enum { enum_name, .. } if enum_name == "Option")
1236 {
1237 return true;
1238 }
1239
1240 if type_name == "Result"
1241 && matches!(value, Value::Enum { enum_name, .. } if enum_name == "Result")
1242 {
1243 return true;
1244 }
1245
1246 if type_name == "unknown" {
1247 return true;
1248 }
1249
1250 if let Some(_) = self
1251 .trait_impls
1252 .get(&(value_type_name.to_string(), type_name.to_string()))
1253 {
1254 return true;
1255 }
1256
1257 false
1258 }
1259
1260 pub(super) fn get_register(&self, reg: Register) -> Result<&Value> {
1261 let frame = self
1262 .call_stack
1263 .last()
1264 .ok_or_else(|| LustError::RuntimeError {
1265 message: "Empty call stack".to_string(),
1266 })?;
1267 Ok(&frame.registers[reg as usize])
1268 }
1269
1270 pub(super) fn set_register(&mut self, reg: Register, value: Value) -> Result<()> {
1271 self.observe_value(&value);
1272 let frame = self
1273 .call_stack
1274 .last_mut()
1275 .ok_or_else(|| LustError::RuntimeError {
1276 message: "Empty call stack".to_string(),
1277 })?;
1278 frame.registers[reg as usize] = value;
1279 self.maybe_collect_cycles();
1280 Ok(())
1281 }
1282
1283 pub(super) fn handle_native_call_outcome(
1284 &mut self,
1285 dest: Register,
1286 outcome: NativeCallResult,
1287 ) -> Result<()> {
1288 match outcome {
1289 NativeCallResult::Return(value) => self.set_register(dest, value),
1290 NativeCallResult::Yield(value) => {
1291 if self.current_task.is_some() {
1292 self.set_register(dest, Value::Nil)?;
1293 self.pending_task_signal = Some(TaskSignal::Yield { dest, value });
1294 Ok(())
1295 } else {
1296 Err(LustError::RuntimeError {
1297 message: "task.yield() can only be used inside a task".to_string(),
1298 })
1299 }
1300 }
1301
1302 NativeCallResult::Stop(value) => {
1303 if self.current_task.is_some() {
1304 self.set_register(dest, Value::Nil)?;
1305 self.pending_task_signal = Some(TaskSignal::Stop { value });
1306 Ok(())
1307 } else {
1308 Err(LustError::RuntimeError {
1309 message: "task.stop() can only be used inside a task".to_string(),
1310 })
1311 }
1312 }
1313 }
1314 }
1315
1316 pub fn value_to_string_for_concat(&mut self, value: &Value) -> Result<Rc<String>> {
1317 match value {
1318 Value::String(s) => Ok(s.clone()),
1319 Value::Struct { name, .. } => self.invoke_tostring(value, name),
1320 Value::Enum { enum_name, .. } => self.invoke_tostring(value, enum_name),
1321 _ => Ok(Rc::new(value.to_string())),
1322 }
1323 }
1324
1325 pub fn call_value(&mut self, func: &Value, args: Vec<Value>) -> Result<Value> {
1326 match func {
1327 Value::Function(func_idx) => {
1328 let mut frame = CallFrame {
1329 function_idx: *func_idx,
1330 ip: 0,
1331 registers: array::from_fn(|_| Value::Nil),
1332 base_register: 0,
1333 return_dest: None,
1334 upvalues: Vec::new(),
1335 };
1336 for (i, arg) in args.into_iter().enumerate() {
1337 frame.registers[i] = arg;
1338 }
1339
1340 let stack_depth_before = self.call_stack.len();
1341 self.call_stack.push(frame);
1342 let previous_target = self.call_until_depth;
1343 self.call_until_depth = Some(stack_depth_before);
1344 let run_result = self.run();
1345 self.call_until_depth = previous_target;
1346 run_result
1347 }
1348
1349 Value::Closure {
1350 function_idx: func_idx,
1351 upvalues,
1352 } => {
1353 let upvalue_values: Vec<Value> = upvalues.iter().map(|uv| uv.get()).collect();
1354 let mut frame = CallFrame {
1355 function_idx: *func_idx,
1356 ip: 0,
1357 registers: array::from_fn(|_| Value::Nil),
1358 base_register: 0,
1359 return_dest: None,
1360 upvalues: upvalue_values,
1361 };
1362 for (i, arg) in args.into_iter().enumerate() {
1363 frame.registers[i] = arg;
1364 }
1365
1366 let stack_depth_before = self.call_stack.len();
1367 self.call_stack.push(frame);
1368 let previous_target = self.call_until_depth;
1369 self.call_until_depth = Some(stack_depth_before);
1370 let run_result = self.run();
1371 self.call_until_depth = previous_target;
1372 run_result
1373 }
1374
1375 Value::NativeFunction(native_fn) => {
1376 self.push_current_vm();
1377 let outcome = native_fn(&args);
1378 self.pop_current_vm();
1379 let outcome = outcome.map_err(|e| LustError::RuntimeError { message: e })?;
1380 match outcome {
1381 NativeCallResult::Return(value) => Ok(value),
1382 NativeCallResult::Yield(_) | NativeCallResult::Stop(_) => {
1383 Err(LustError::RuntimeError {
1384 message: "Yielding or stopping is not allowed from this context"
1385 .to_string(),
1386 })
1387 }
1388 }
1389 }
1390
1391 _ => Err(LustError::RuntimeError {
1392 message: format!("Cannot call non-function value: {:?}", func),
1393 }),
1394 }
1395 }
1396}