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                        _ => Err(LustError::RuntimeError {
431                            message: format!("Cannot modulo {:?} and {:?}", l, r),
432                        }),
433                    })?;
434                }
435
436                Instruction::Neg(dest, src) => {
437                    let value = self.get_register(src)?;
438                    let result = match value {
439                        Value::Int(i) => Value::Int(-i),
440                        Value::Float(f) => Value::Float(-f),
441                        _ => {
442                            return Err(LustError::RuntimeError {
443                                message: format!("Cannot negate {:?}", value),
444                            })
445                        }
446                    };
447                    self.set_register(dest, result)?;
448                }
449
450                Instruction::Eq(dest, lhs, rhs) => {
451                    let left = self.get_register(lhs)?;
452                    let right = self.get_register(rhs)?;
453                    self.set_register(dest, Value::Bool(left == right))?;
454                }
455
456                Instruction::Ne(dest, lhs, rhs) => {
457                    let left = self.get_register(lhs)?;
458                    let right = self.get_register(rhs)?;
459                    self.set_register(dest, Value::Bool(left != right))?;
460                }
461
462                Instruction::Lt(dest, lhs, rhs) => {
463                    self.comparison_op(dest, lhs, rhs, |l, r| l < r)?;
464                }
465
466                Instruction::Le(dest, lhs, rhs) => {
467                    self.comparison_op(dest, lhs, rhs, |l, r| l <= r)?;
468                }
469
470                Instruction::Gt(dest, lhs, rhs) => {
471                    self.comparison_op(dest, lhs, rhs, |l, r| l > r)?;
472                }
473
474                Instruction::Ge(dest, lhs, rhs) => {
475                    self.comparison_op(dest, lhs, rhs, |l, r| l >= r)?;
476                }
477
478                Instruction::And(dest, lhs, rhs) => {
479                    let left = self.get_register(lhs)?;
480                    let right = self.get_register(rhs)?;
481                    let result = Value::Bool(left.is_truthy() && right.is_truthy());
482                    self.set_register(dest, result)?;
483                }
484
485                Instruction::Or(dest, lhs, rhs) => {
486                    let left = self.get_register(lhs)?;
487                    let right = self.get_register(rhs)?;
488                    let result = Value::Bool(left.is_truthy() || right.is_truthy());
489                    self.set_register(dest, result)?;
490                }
491
492                Instruction::Not(dest, src) => {
493                    let value = self.get_register(src)?;
494                    self.set_register(dest, Value::Bool(!value.is_truthy()))?;
495                }
496
497                Instruction::Jump(offset) => {
498                    let frame = self.call_stack.last_mut().unwrap();
499                    frame.ip = (frame.ip as isize + offset as isize) as usize;
500                }
501
502                Instruction::JumpIf(cond, offset) => {
503                    let condition = self.get_register(cond)?;
504                    if condition.is_truthy() {
505                        let frame = self.call_stack.last_mut().unwrap();
506                        frame.ip = (frame.ip as isize + offset as isize) as usize;
507                    }
508                }
509
510                Instruction::JumpIfNot(cond, offset) => {
511                    let condition = self.get_register(cond)?;
512                    if !condition.is_truthy() {
513                        let frame = self.call_stack.last_mut().unwrap();
514                        frame.ip = (frame.ip as isize + offset as isize) as usize;
515                    }
516                }
517
518                Instruction::Call(func_reg, first_arg, arg_count, dest_reg) => {
519                    let func_value = self.get_register(func_reg)?.clone();
520                    match func_value {
521                        Value::Function(func_idx) => {
522                            let mut args = Vec::new();
523                            for i in 0..arg_count {
524                                args.push(self.get_register(first_arg + i)?.clone());
525                            }
526
527                            let mut frame = CallFrame {
528                                function_idx: func_idx,
529                                ip: 0,
530                                registers: array::from_fn(|_| Value::Nil),
531                                base_register: 0,
532                                return_dest: Some(dest_reg),
533                                upvalues: Vec::new(),
534                            };
535                            for (i, arg) in args.into_iter().enumerate() {
536                                frame.registers[i] = arg;
537                            }
538
539                            self.call_stack.push(frame);
540                        }
541
542                        Value::Closure {
543                            function_idx: func_idx,
544                            upvalues,
545                        } => {
546                            let mut args = Vec::new();
547                            for i in 0..arg_count {
548                                args.push(self.get_register(first_arg + i)?.clone());
549                            }
550
551                            let upvalue_values: Vec<Value> =
552                                upvalues.iter().map(|uv| uv.get()).collect();
553                            let mut frame = CallFrame {
554                                function_idx: func_idx,
555                                ip: 0,
556                                registers: array::from_fn(|_| Value::Nil),
557                                base_register: 0,
558                                return_dest: Some(dest_reg),
559                                upvalues: upvalue_values,
560                            };
561                            for (i, arg) in args.into_iter().enumerate() {
562                                frame.registers[i] = arg;
563                            }
564
565                            self.call_stack.push(frame);
566                        }
567
568                        Value::NativeFunction(native_fn) => {
569                            let mut args = Vec::new();
570                            for i in 0..arg_count {
571                                args.push(self.get_register(first_arg + i)?.clone());
572                            }
573
574                            self.push_current_vm();
575                            let outcome = native_fn(&args);
576                            self.pop_current_vm();
577                            let outcome =
578                                outcome.map_err(|e| LustError::RuntimeError { message: e })?;
579                            self.handle_native_call_outcome(dest_reg, outcome)?;
580                        }
581
582                        _ => {
583                            return Err(LustError::RuntimeError {
584                                message: format!(
585                                    "Cannot call non-function value: {:?}",
586                                    func_value
587                                ),
588                            })
589                        }
590                    }
591                }
592
593                Instruction::Return(value_reg) => {
594                    let return_value = if value_reg == 255 {
595                        Value::Nil
596                    } else {
597                        self.get_register(value_reg)?.clone()
598                    };
599                    let return_dest = self.call_stack.last().unwrap().return_dest;
600                    self.call_stack.pop();
601                    if self.call_stack.is_empty() {
602                        return Ok(return_value);
603                    }
604
605                    self.pending_return_value = Some(return_value);
606                    self.pending_return_dest = return_dest;
607                }
608
609                Instruction::NewArray(dest, first_elem, count) => {
610                    let mut elements = Vec::new();
611                    for i in 0..count {
612                        elements.push(self.get_register(first_elem + i)?.clone());
613                    }
614
615                    self.set_register(dest, Value::array(elements))?;
616                }
617
618                Instruction::TupleNew(dest, first_elem, count) => {
619                    let mut elements = Vec::new();
620                    for offset in 0..(count as usize) {
621                        let value = self.get_register(first_elem + offset as u8)?.clone();
622                        if let Value::Tuple(existing) = value {
623                            elements.extend(existing.iter().cloned());
624                        } else {
625                            elements.push(value);
626                        }
627                    }
628
629                    self.set_register(dest, Value::tuple(elements))?;
630                }
631
632                Instruction::TupleGet(dest, tuple_reg, index) => {
633                    let tuple_value = self.get_register(tuple_reg)?.clone();
634                    if let Value::Tuple(values) = tuple_value {
635                        let idx = index as usize;
636                        if idx >= values.len() {
637                            return Err(LustError::RuntimeError {
638                                message: format!(
639                                    "Tuple index {} out of bounds (len {})",
640                                    idx,
641                                    values.len()
642                                ),
643                            });
644                        }
645
646                        let value = values[idx].clone();
647                        self.set_register(dest, value)?;
648                    } else {
649                        return Err(LustError::RuntimeError {
650                            message: "Attempted to destructure non-tuple value".to_string(),
651                        });
652                    }
653                }
654
655                Instruction::NewMap(dest) => {
656                    self.set_register(dest, Value::map(HashMap::new()))?;
657                }
658
659                Instruction::NewTable(dest) => {
660                    self.set_register(dest, Value::table(HashMap::new()))?;
661                }
662
663                Instruction::NewStruct(
664                    dest,
665                    name_idx,
666                    first_field_name_idx,
667                    first_field,
668                    field_count,
669                ) => {
670                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
671                    let struct_name = func.chunk.constants[name_idx as usize]
672                        .as_string()
673                        .ok_or_else(|| LustError::RuntimeError {
674                            message: "Struct name must be a string".to_string(),
675                        })?
676                        .to_string();
677                    let mut fields = Vec::with_capacity(field_count as usize);
678                    for i in 0..field_count {
679                        let field_name = func.chunk.constants
680                            [(first_field_name_idx + i as u16) as usize]
681                            .as_string_rc()
682                            .ok_or_else(|| LustError::RuntimeError {
683                                message: "Field name must be a string".to_string(),
684                            })?;
685                        let value = self.get_register(first_field + i)?.clone();
686                        fields.push((field_name, value));
687                    }
688
689                    let struct_value = self.instantiate_struct(&struct_name, fields)?;
690                    self.set_register(dest, struct_value)?;
691                }
692
693                Instruction::NewEnumUnit(dest, enum_name_idx, variant_idx) => {
694                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
695                    let enum_name = func.chunk.constants[enum_name_idx as usize]
696                        .as_string()
697                        .ok_or_else(|| LustError::RuntimeError {
698                            message: "Enum name must be a string".to_string(),
699                        })?
700                        .to_string();
701                    let variant_name = func.chunk.constants[variant_idx as usize]
702                        .as_string()
703                        .ok_or_else(|| LustError::RuntimeError {
704                            message: "Variant name must be a string".to_string(),
705                        })?
706                        .to_string();
707                    self.set_register(dest, Value::enum_unit(enum_name, variant_name))?;
708                }
709
710                Instruction::NewEnumVariant(
711                    dest,
712                    enum_name_idx,
713                    variant_idx,
714                    first_value,
715                    value_count,
716                ) => {
717                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
718                    let enum_name = func.chunk.constants[enum_name_idx as usize]
719                        .as_string()
720                        .ok_or_else(|| LustError::RuntimeError {
721                            message: "Enum name must be a string".to_string(),
722                        })?
723                        .to_string();
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                        .to_string();
730                    let mut values = Vec::new();
731                    for i in 0..value_count {
732                        values.push(self.get_register(first_value + i)?.clone());
733                    }
734
735                    self.set_register(dest, Value::enum_variant(enum_name, variant_name, values))?;
736                }
737
738                Instruction::IsEnumVariant(dest, value_reg, enum_name_idx, variant_idx) => {
739                    let value = self.get_register(value_reg)?;
740                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
741                    let enum_name = func.chunk.constants[enum_name_idx as usize]
742                        .as_string()
743                        .ok_or_else(|| LustError::RuntimeError {
744                            message: "Enum name must be a string".to_string(),
745                        })?;
746                    let variant_name = func.chunk.constants[variant_idx as usize]
747                        .as_string()
748                        .ok_or_else(|| LustError::RuntimeError {
749                            message: "Variant name must be a string".to_string(),
750                        })?;
751                    let is_variant = value.is_enum_variant(enum_name, variant_name);
752                    self.set_register(dest, Value::Bool(is_variant))?;
753                }
754
755                Instruction::GetEnumValue(dest, enum_reg, index) => {
756                    let enum_value = self.get_register(enum_reg)?;
757                    if let Some((_, _, Some(values))) = enum_value.as_enum() {
758                        if (index as usize) < values.len() {
759                            self.set_register(dest, values[index as usize].clone())?;
760                        } else {
761                            return Err(LustError::RuntimeError {
762                                message: format!(
763                                    "Enum value index {} out of bounds (has {} values)",
764                                    index,
765                                    values.len()
766                                ),
767                            });
768                        }
769                    } else {
770                        return Err(LustError::RuntimeError {
771                            message: "GetEnumValue requires an enum variant with values"
772                                .to_string(),
773                        });
774                    }
775                }
776
777                Instruction::GetField(dest, obj, field_idx) => {
778                    let object = self.get_register(obj)?;
779                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
780                    let field_name = func.chunk.constants[field_idx as usize]
781                        .as_string_rc()
782                        .ok_or_else(|| LustError::RuntimeError {
783                            message: "Field name must be a string".to_string(),
784                        })?;
785                    let value = match object {
786                        Value::Struct { .. } => object
787                            .struct_get_field_rc(&field_name)
788                            .unwrap_or(Value::Nil),
789                        Value::Map(map) => {
790                            use crate::bytecode::ValueKey;
791                            let key = ValueKey::String(field_name.clone());
792                            map.borrow().get(&key).cloned().unwrap_or(Value::Nil)
793                        }
794
795                        Value::Table(table) => {
796                            use crate::bytecode::ValueKey;
797                            let key = ValueKey::String(field_name.clone());
798                            table.borrow().get(&key).cloned().unwrap_or(Value::Nil)
799                        }
800
801                        _ => {
802                            return Err(LustError::RuntimeError {
803                                message: format!(
804                                    "Cannot get field '{}' from {:?}",
805                                    field_name.as_str(),
806                                    object
807                                ),
808                            })
809                        }
810                    };
811                    self.set_register(dest, value)?;
812                }
813
814                Instruction::SetField(obj_reg, field_idx, value_reg) => {
815                    let object = self.get_register(obj_reg)?;
816                    let value = self.get_register(value_reg)?.clone();
817                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
818                    let field_name = func.chunk.constants[field_idx as usize]
819                        .as_string_rc()
820                        .ok_or_else(|| LustError::RuntimeError {
821                            message: "Field name must be a string".to_string(),
822                        })?;
823                    let mut invalidate_key: Option<usize> = None;
824                    match object {
825                        Value::Struct { .. } => {
826                            invalidate_key = Self::struct_cache_key(object);
827                            object
828                                .struct_set_field_rc(&field_name, value)
829                                .map_err(|message| LustError::RuntimeError { message })?;
830                        }
831
832                        Value::Map(map) => {
833                            use crate::bytecode::ValueKey;
834                            let key = ValueKey::String(field_name.clone());
835                            map.borrow_mut().insert(key, value);
836                        }
837
838                        _ => {
839                            return Err(LustError::RuntimeError {
840                                message: format!(
841                                    "Cannot set field '{}' on {:?}",
842                                    field_name.as_str(),
843                                    object
844                                ),
845                            })
846                        }
847                    }
848
849                    if let Some(key) = invalidate_key {
850                        self.struct_tostring_cache.remove(&key);
851                    }
852                }
853
854                Instruction::Concat(dest, lhs, rhs) => {
855                    let (left, right) = {
856                        let frame =
857                            self.call_stack
858                                .last_mut()
859                                .ok_or_else(|| LustError::RuntimeError {
860                                    message: "Empty call stack".to_string(),
861                                })?;
862                        let left = frame.registers[lhs as usize].clone();
863                        let right = frame.registers[rhs as usize].clone();
864                        (left, right)
865                    };
866                    let left_str = self.value_to_string_for_concat(&left)?;
867                    let right_str = self.value_to_string_for_concat(&right)?;
868                    let mut combined = String::with_capacity(left_str.len() + right_str.len());
869                    combined.push_str(left_str.as_ref());
870                    combined.push_str(right_str.as_ref());
871                    let result = Value::string(combined);
872                    self.set_register(dest, result)?;
873                }
874
875                Instruction::GetIndex(dest, array_reg, index_reg) => {
876                    let collection = self.get_register(array_reg)?;
877                    let index = self.get_register(index_reg)?;
878                    let result = match collection {
879                        Value::Array(arr) => {
880                            let idx = index.as_int().ok_or_else(|| LustError::RuntimeError {
881                                message: "Array index must be an integer".to_string(),
882                            })?;
883                            let borrowed = arr.borrow();
884                            if idx < 0 || idx as usize >= borrowed.len() {
885                                return Err(LustError::RuntimeError {
886                                    message: format!(
887                                        "Array index {} out of bounds (length: {})",
888                                        idx,
889                                        borrowed.len()
890                                    ),
891                                });
892                            }
893
894                            borrowed[idx as usize].clone()
895                        }
896
897                        Value::Map(map) => {
898                            use crate::bytecode::ValueKey;
899                            let key = ValueKey::from_value(index).ok_or_else(|| {
900                                LustError::RuntimeError {
901                                    message: format!(
902                                        "Cannot use {:?} as map key (not hashable)",
903                                        index
904                                    ),
905                                }
906                            })?;
907                            map.borrow().get(&key).cloned().unwrap_or(Value::Nil)
908                        }
909
910                        Value::Table(table) => {
911                            use crate::bytecode::ValueKey;
912                            let key = ValueKey::from_value(index).ok_or_else(|| {
913                                LustError::RuntimeError {
914                                    message: format!(
915                                        "Cannot use {:?} as table key (not hashable)",
916                                        index
917                                    ),
918                                }
919                            })?;
920                            table.borrow().get(&key).cloned().unwrap_or(Value::Nil)
921                        }
922
923                        _ => {
924                            return Err(LustError::RuntimeError {
925                                message: format!("Cannot index {:?}", collection.type_of()),
926                            })
927                        }
928                    };
929                    self.set_register(dest, result)?;
930                }
931
932                Instruction::ArrayLen(dest, array_reg) => {
933                    let collection = self.get_register(array_reg)?;
934                    match collection {
935                        Value::Array(arr) => {
936                            let len = int_from_usize(arr.borrow().len());
937                            self.set_register(dest, Value::Int(len))?;
938                        }
939
940                        _ => {
941                            return Err(LustError::RuntimeError {
942                                message: format!(
943                                    "ArrayLen requires array, got {:?}",
944                                    collection.type_of()
945                                ),
946                            });
947                        }
948                    }
949                }
950
951                Instruction::CallMethod(
952                    obj_reg,
953                    method_name_idx,
954                    first_arg,
955                    arg_count,
956                    dest_reg,
957                ) => {
958                    let object = self.get_register(obj_reg)?.clone();
959                    let method_name = {
960                        let func = &self.functions[self.call_stack.last().unwrap().function_idx];
961                        func.chunk.constants[method_name_idx as usize]
962                            .as_string()
963                            .ok_or_else(|| LustError::RuntimeError {
964                                message: "Method name must be a string".to_string(),
965                            })?
966                            .to_string()
967                    };
968                    if let Value::Struct {
969                        name: struct_name, ..
970                    } = &object
971                    {
972                        let mangled_name = format!("{}:{}", struct_name, method_name);
973                        if let Some(func_idx) =
974                            self.functions.iter().position(|f| f.name == mangled_name)
975                        {
976                            let mut frame = CallFrame {
977                                function_idx: func_idx,
978                                ip: 0,
979                                registers: array::from_fn(|_| Value::Nil),
980                                base_register: 0,
981                                return_dest: Some(dest_reg),
982                                upvalues: Vec::new(),
983                            };
984                            frame.registers[0] = object.clone();
985                            for i in 0..arg_count {
986                                frame.registers[(i + 1) as usize] =
987                                    self.get_register(first_arg + i)?.clone();
988                            }
989
990                            self.call_stack.push(frame);
991                            continue;
992                        }
993                    }
994
995                    let mut args = Vec::new();
996                    for i in 0..arg_count {
997                        args.push(self.get_register(first_arg + i)?.clone());
998                    }
999
1000                    let result = self.call_builtin_method(&object, &method_name, args)?;
1001                    self.set_register(dest_reg, result)?;
1002                }
1003
1004                Instruction::Closure(dest, func_idx, first_upvalue_reg, upvalue_count) => {
1005                    use crate::bytecode::Upvalue;
1006                    let mut upvalues = Vec::new();
1007                    for i in 0..upvalue_count {
1008                        let value = self.get_register(first_upvalue_reg + i)?.clone();
1009                        upvalues.push(Upvalue::new(value));
1010                    }
1011
1012                    let closure = Value::Closure {
1013                        function_idx: func_idx as usize,
1014                        upvalues: Rc::new(upvalues),
1015                    };
1016                    self.set_register(dest, closure)?;
1017                }
1018
1019                Instruction::LoadUpvalue(dest, upvalue_idx) => {
1020                    let frame = self
1021                        .call_stack
1022                        .last()
1023                        .ok_or_else(|| LustError::RuntimeError {
1024                            message: "Empty call stack".to_string(),
1025                        })?;
1026                    if (upvalue_idx as usize) < frame.upvalues.len() {
1027                        let value = frame.upvalues[upvalue_idx as usize].clone();
1028                        self.set_register(dest, value)?;
1029                    } else {
1030                        return Err(LustError::RuntimeError {
1031                            message: format!(
1032                                "Upvalue index {} out of bounds (have {} upvalues)",
1033                                upvalue_idx,
1034                                frame.upvalues.len()
1035                            ),
1036                        });
1037                    }
1038                }
1039
1040                Instruction::StoreUpvalue(upvalue_idx, src) => {
1041                    let value = self.get_register(src)?.clone();
1042                    let frame =
1043                        self.call_stack
1044                            .last_mut()
1045                            .ok_or_else(|| LustError::RuntimeError {
1046                                message: "Empty call stack".to_string(),
1047                            })?;
1048                    if (upvalue_idx as usize) < frame.upvalues.len() {
1049                        frame.upvalues[upvalue_idx as usize] = value;
1050                    } else {
1051                        return Err(LustError::RuntimeError {
1052                            message: format!(
1053                                "Upvalue index {} out of bounds (have {} upvalues)",
1054                                upvalue_idx,
1055                                frame.upvalues.len()
1056                            ),
1057                        });
1058                    }
1059                }
1060
1061                Instruction::SetIndex(collection_reg, index_reg, value_reg) => {
1062                    let collection = self.get_register(collection_reg)?;
1063                    let index = self.get_register(index_reg)?;
1064                    let value = self.get_register(value_reg)?.clone();
1065                    match collection {
1066                        Value::Array(arr) => {
1067                            let idx = index.as_int().ok_or_else(|| LustError::RuntimeError {
1068                                message: "Array index must be an integer".to_string(),
1069                            })?;
1070                            let mut borrowed = arr.borrow_mut();
1071                            if idx < 0 || idx as usize >= borrowed.len() {
1072                                return Err(LustError::RuntimeError {
1073                                    message: format!(
1074                                        "Array index {} out of bounds (length: {})",
1075                                        idx,
1076                                        borrowed.len()
1077                                    ),
1078                                });
1079                            }
1080
1081                            borrowed[idx as usize] = value;
1082                        }
1083
1084                        Value::Map(map) => {
1085                            use crate::bytecode::ValueKey;
1086                            let key = ValueKey::from_value(index).ok_or_else(|| {
1087                                LustError::RuntimeError {
1088                                    message: format!(
1089                                        "Cannot use {:?} as map key (not hashable)",
1090                                        index
1091                                    ),
1092                                }
1093                            })?;
1094                            map.borrow_mut().insert(key, value);
1095                        }
1096
1097                        Value::Table(table) => {
1098                            use crate::bytecode::ValueKey;
1099                            let key = ValueKey::from_value(index).ok_or_else(|| {
1100                                LustError::RuntimeError {
1101                                    message: format!(
1102                                        "Cannot use {:?} as table key (not hashable)",
1103                                        index
1104                                    ),
1105                                }
1106                            })?;
1107                            table.borrow_mut().insert(key, value);
1108                        }
1109
1110                        _ => {
1111                            return Err(LustError::RuntimeError {
1112                                message: format!("Cannot index {:?}", collection.type_of()),
1113                            })
1114                        }
1115                    }
1116                }
1117
1118                Instruction::TypeIs(dest, value_reg, type_name_idx) => {
1119                    let value = self.get_register(value_reg)?.clone();
1120                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
1121                    let type_name = func.chunk.constants[type_name_idx as usize]
1122                        .as_string()
1123                        .ok_or_else(|| LustError::RuntimeError {
1124                            message: "Type name must be a string".to_string(),
1125                        })?
1126                        .to_string();
1127                    let matches = self.value_is_type(&value, &type_name);
1128                    self.set_register(dest, Value::Bool(matches))?;
1129                }
1130            }
1131
1132            if self.jit.enabled {
1133                if let Some(recorder) = &mut self.trace_recorder {
1134                    if recorder.is_recording() {
1135                        if self.skip_next_trace_record {
1136                            self.skip_next_trace_record = false;
1137                        } else {
1138                            let function = &self.functions[func_idx];
1139                            if let Some(frame) = self.call_stack.last() {
1140                                if let Err(e) = recorder.record_instruction(
1141                                    instruction,
1142                                    ip_before_execution,
1143                                    &frame.registers,
1144                                    function,
1145                                    func_idx,
1146                                ) {
1147                                    crate::jit::log(|| format!("⚠️  JIT: {}", e));
1148                                    self.trace_recorder = None;
1149                                }
1150                            }
1151                        }
1152                    }
1153                }
1154            }
1155        }
1156    }
1157
1158    pub(super) fn binary_op<F>(
1159        &mut self,
1160        dest: Register,
1161        lhs: Register,
1162        rhs: Register,
1163        op: F,
1164    ) -> Result<()>
1165    where
1166        F: FnOnce(&Value, &Value) -> Result<Value>,
1167    {
1168        let left = self.get_register(lhs)?;
1169        let right = self.get_register(rhs)?;
1170        let result = op(left, right)?;
1171        self.set_register(dest, result)
1172    }
1173
1174    pub(super) fn comparison_op<F>(
1175        &mut self,
1176        dest: Register,
1177        lhs: Register,
1178        rhs: Register,
1179        op: F,
1180    ) -> Result<()>
1181    where
1182        F: FnOnce(LustFloat, LustFloat) -> bool,
1183    {
1184        let left = self.get_register(lhs)?;
1185        let right = self.get_register(rhs)?;
1186        let result = match (left, right) {
1187            (Value::Int(a), Value::Int(b)) => op(float_from_int(*a), float_from_int(*b)),
1188            (Value::Float(a), Value::Float(b)) => op(*a, *b),
1189            (Value::Int(a), Value::Float(b)) => op(float_from_int(*a), *b),
1190            (Value::Float(a), Value::Int(b)) => op(*a, float_from_int(*b)),
1191            _ => {
1192                return Err(LustError::RuntimeError {
1193                    message: format!("Cannot compare {:?} and {:?}", left, right),
1194                })
1195            }
1196        };
1197        self.set_register(dest, Value::Bool(result))
1198    }
1199
1200    pub(super) fn value_is_type(&self, value: &Value, type_name: &str) -> bool {
1201        let value_type_name = match value {
1202            Value::Int(_) => "int",
1203            Value::Float(_) => "float",
1204            Value::String(_) => "string",
1205            Value::Bool(_) => "bool",
1206            Value::Nil => "nil",
1207            Value::Array(_) => "Array",
1208            Value::Tuple(_) => "Tuple",
1209            Value::Map(_) => "Map",
1210            Value::Table(_) => "Table",
1211            Value::Struct { name, .. } => name.as_str(),
1212            Value::WeakStruct(weak) => weak.struct_name(),
1213            Value::Enum { enum_name, .. } => enum_name.as_str(),
1214            Value::Function(_) | Value::NativeFunction(_) | Value::Closure { .. } => "function",
1215            Value::Iterator(_) => "Iterator",
1216            Value::Task(_) => "task",
1217        };
1218        if value_type_name == type_name {
1219            return true;
1220        }
1221
1222        if type_name.starts_with("Array") && matches!(value, Value::Array(_)) {
1223            return true;
1224        }
1225
1226        if type_name.starts_with("Map") && matches!(value, Value::Map(_)) {
1227            return true;
1228        }
1229
1230        if type_name.starts_with("Tuple") && matches!(value, Value::Tuple(_)) {
1231            return true;
1232        }
1233
1234        if type_name == "Option"
1235            && matches!(value, Value::Enum { enum_name, .. } if enum_name == "Option")
1236        {
1237            return true;
1238        }
1239
1240        if type_name == "Result"
1241            && matches!(value, Value::Enum { enum_name, .. } if enum_name == "Result")
1242        {
1243            return true;
1244        }
1245
1246        if type_name == "unknown" {
1247            return true;
1248        }
1249
1250        if let Some(_) = self
1251            .trait_impls
1252            .get(&(value_type_name.to_string(), type_name.to_string()))
1253        {
1254            return true;
1255        }
1256
1257        false
1258    }
1259
1260    pub(super) fn get_register(&self, reg: Register) -> Result<&Value> {
1261        let frame = self
1262            .call_stack
1263            .last()
1264            .ok_or_else(|| LustError::RuntimeError {
1265                message: "Empty call stack".to_string(),
1266            })?;
1267        Ok(&frame.registers[reg as usize])
1268    }
1269
1270    pub(super) fn set_register(&mut self, reg: Register, value: Value) -> Result<()> {
1271        self.observe_value(&value);
1272        let frame = self
1273            .call_stack
1274            .last_mut()
1275            .ok_or_else(|| LustError::RuntimeError {
1276                message: "Empty call stack".to_string(),
1277            })?;
1278        frame.registers[reg as usize] = value;
1279        self.maybe_collect_cycles();
1280        Ok(())
1281    }
1282
1283    pub(super) fn handle_native_call_outcome(
1284        &mut self,
1285        dest: Register,
1286        outcome: NativeCallResult,
1287    ) -> Result<()> {
1288        match outcome {
1289            NativeCallResult::Return(value) => self.set_register(dest, value),
1290            NativeCallResult::Yield(value) => {
1291                if self.current_task.is_some() {
1292                    self.set_register(dest, Value::Nil)?;
1293                    self.pending_task_signal = Some(TaskSignal::Yield { dest, value });
1294                    Ok(())
1295                } else {
1296                    Err(LustError::RuntimeError {
1297                        message: "task.yield() can only be used inside a task".to_string(),
1298                    })
1299                }
1300            }
1301
1302            NativeCallResult::Stop(value) => {
1303                if self.current_task.is_some() {
1304                    self.set_register(dest, Value::Nil)?;
1305                    self.pending_task_signal = Some(TaskSignal::Stop { value });
1306                    Ok(())
1307                } else {
1308                    Err(LustError::RuntimeError {
1309                        message: "task.stop() can only be used inside a task".to_string(),
1310                    })
1311                }
1312            }
1313        }
1314    }
1315
1316    pub fn value_to_string_for_concat(&mut self, value: &Value) -> Result<Rc<String>> {
1317        match value {
1318            Value::String(s) => Ok(s.clone()),
1319            Value::Struct { name, .. } => self.invoke_tostring(value, name),
1320            Value::Enum { enum_name, .. } => self.invoke_tostring(value, enum_name),
1321            _ => Ok(Rc::new(value.to_string())),
1322        }
1323    }
1324
1325    pub fn call_value(&mut self, func: &Value, args: Vec<Value>) -> Result<Value> {
1326        match func {
1327            Value::Function(func_idx) => {
1328                let mut frame = CallFrame {
1329                    function_idx: *func_idx,
1330                    ip: 0,
1331                    registers: array::from_fn(|_| Value::Nil),
1332                    base_register: 0,
1333                    return_dest: None,
1334                    upvalues: Vec::new(),
1335                };
1336                for (i, arg) in args.into_iter().enumerate() {
1337                    frame.registers[i] = arg;
1338                }
1339
1340                let stack_depth_before = self.call_stack.len();
1341                self.call_stack.push(frame);
1342                let previous_target = self.call_until_depth;
1343                self.call_until_depth = Some(stack_depth_before);
1344                let run_result = self.run();
1345                self.call_until_depth = previous_target;
1346                run_result
1347            }
1348
1349            Value::Closure {
1350                function_idx: func_idx,
1351                upvalues,
1352            } => {
1353                let upvalue_values: Vec<Value> = upvalues.iter().map(|uv| uv.get()).collect();
1354                let mut frame = CallFrame {
1355                    function_idx: *func_idx,
1356                    ip: 0,
1357                    registers: array::from_fn(|_| Value::Nil),
1358                    base_register: 0,
1359                    return_dest: None,
1360                    upvalues: upvalue_values,
1361                };
1362                for (i, arg) in args.into_iter().enumerate() {
1363                    frame.registers[i] = arg;
1364                }
1365
1366                let stack_depth_before = self.call_stack.len();
1367                self.call_stack.push(frame);
1368                let previous_target = self.call_until_depth;
1369                self.call_until_depth = Some(stack_depth_before);
1370                let run_result = self.run();
1371                self.call_until_depth = previous_target;
1372                run_result
1373            }
1374
1375            Value::NativeFunction(native_fn) => {
1376                self.push_current_vm();
1377                let outcome = native_fn(&args);
1378                self.pop_current_vm();
1379                let outcome = outcome.map_err(|e| LustError::RuntimeError { message: e })?;
1380                match outcome {
1381                    NativeCallResult::Return(value) => Ok(value),
1382                    NativeCallResult::Yield(_) | NativeCallResult::Stop(_) => {
1383                        Err(LustError::RuntimeError {
1384                            message: "Yielding or stopping is not allowed from this context"
1385                                .to_string(),
1386                        })
1387                    }
1388                }
1389            }
1390
1391            _ => Err(LustError::RuntimeError {
1392                message: format!("Cannot call non-function value: {:?}", func),
1393            }),
1394        }
1395    }
1396}