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