lust/vm/
execution.rs

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