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