lust/vm/
execution.rs

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