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