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::NewStruct(
660                    dest,
661                    name_idx,
662                    first_field_name_idx,
663                    first_field,
664                    field_count,
665                ) => {
666                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
667                    let struct_name = func.chunk.constants[name_idx as usize]
668                        .as_string()
669                        .ok_or_else(|| LustError::RuntimeError {
670                            message: "Struct name must be a string".to_string(),
671                        })?
672                        .to_string();
673                    let mut fields = Vec::with_capacity(field_count as usize);
674                    for i in 0..field_count {
675                        let field_name = func.chunk.constants
676                            [(first_field_name_idx + i as u16) as usize]
677                            .as_string_rc()
678                            .ok_or_else(|| LustError::RuntimeError {
679                                message: "Field name must be a string".to_string(),
680                            })?;
681                        let value = self.get_register(first_field + i)?.clone();
682                        fields.push((field_name, value));
683                    }
684
685                    let struct_value = self.instantiate_struct(&struct_name, fields)?;
686                    self.set_register(dest, struct_value)?;
687                }
688
689                Instruction::NewEnumUnit(dest, enum_name_idx, variant_idx) => {
690                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
691                    let enum_name = func.chunk.constants[enum_name_idx as usize]
692                        .as_string()
693                        .ok_or_else(|| LustError::RuntimeError {
694                            message: "Enum name must be a string".to_string(),
695                        })?
696                        .to_string();
697                    let variant_name = func.chunk.constants[variant_idx as usize]
698                        .as_string()
699                        .ok_or_else(|| LustError::RuntimeError {
700                            message: "Variant name must be a string".to_string(),
701                        })?
702                        .to_string();
703                    self.set_register(dest, Value::enum_unit(enum_name, variant_name))?;
704                }
705
706                Instruction::NewEnumVariant(
707                    dest,
708                    enum_name_idx,
709                    variant_idx,
710                    first_value,
711                    value_count,
712                ) => {
713                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
714                    let enum_name = func.chunk.constants[enum_name_idx as usize]
715                        .as_string()
716                        .ok_or_else(|| LustError::RuntimeError {
717                            message: "Enum name must be a string".to_string(),
718                        })?
719                        .to_string();
720                    let variant_name = func.chunk.constants[variant_idx as usize]
721                        .as_string()
722                        .ok_or_else(|| LustError::RuntimeError {
723                            message: "Variant name must be a string".to_string(),
724                        })?
725                        .to_string();
726                    let mut values = Vec::new();
727                    for i in 0..value_count {
728                        values.push(self.get_register(first_value + i)?.clone());
729                    }
730
731                    self.set_register(dest, Value::enum_variant(enum_name, variant_name, values))?;
732                }
733
734                Instruction::IsEnumVariant(dest, value_reg, enum_name_idx, variant_idx) => {
735                    let value = self.get_register(value_reg)?;
736                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
737                    let enum_name = func.chunk.constants[enum_name_idx as usize]
738                        .as_string()
739                        .ok_or_else(|| LustError::RuntimeError {
740                            message: "Enum name must be a string".to_string(),
741                        })?;
742                    let variant_name = func.chunk.constants[variant_idx as usize]
743                        .as_string()
744                        .ok_or_else(|| LustError::RuntimeError {
745                            message: "Variant name must be a string".to_string(),
746                        })?;
747                    let is_variant = value.is_enum_variant(enum_name, variant_name);
748                    self.set_register(dest, Value::Bool(is_variant))?;
749                }
750
751                Instruction::GetEnumValue(dest, enum_reg, index) => {
752                    let enum_value = self.get_register(enum_reg)?;
753                    if let Some((_, _, Some(values))) = enum_value.as_enum() {
754                        if (index as usize) < values.len() {
755                            self.set_register(dest, values[index as usize].clone())?;
756                        } else {
757                            return Err(LustError::RuntimeError {
758                                message: format!(
759                                    "Enum value index {} out of bounds (has {} values)",
760                                    index,
761                                    values.len()
762                                ),
763                            });
764                        }
765                    } else {
766                        return Err(LustError::RuntimeError {
767                            message: "GetEnumValue requires an enum variant with values"
768                                .to_string(),
769                        });
770                    }
771                }
772
773                Instruction::GetField(dest, obj, field_idx) => {
774                    let object = self.get_register(obj)?;
775                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
776                    let field_name = func.chunk.constants[field_idx as usize]
777                        .as_string_rc()
778                        .ok_or_else(|| LustError::RuntimeError {
779                            message: "Field name must be a string".to_string(),
780                        })?;
781                    let value = match object {
782                        Value::Struct { .. } => object
783                            .struct_get_field_rc(&field_name)
784                            .unwrap_or(Value::Nil),
785                        Value::Map(map) => {
786                            use crate::bytecode::ValueKey;
787                            let key = ValueKey::String(field_name.clone());
788                            map.borrow().get(&key).cloned().unwrap_or(Value::Nil)
789                        }
790
791                        _ => {
792                            return Err(LustError::RuntimeError {
793                                message: format!(
794                                    "Cannot get field '{}' from {:?}",
795                                    field_name.as_str(),
796                                    object
797                                ),
798                            })
799                        }
800                    };
801                    self.set_register(dest, value)?;
802                }
803
804                Instruction::SetField(obj_reg, field_idx, value_reg) => {
805                    let object = self.get_register(obj_reg)?;
806                    let value = self.get_register(value_reg)?.clone();
807                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
808                    let field_name = func.chunk.constants[field_idx as usize]
809                        .as_string_rc()
810                        .ok_or_else(|| LustError::RuntimeError {
811                            message: "Field name must be a string".to_string(),
812                        })?;
813                    let mut invalidate_key: Option<usize> = None;
814                    match object {
815                        Value::Struct { .. } => {
816                            invalidate_key = Self::struct_cache_key(object);
817                            object
818                                .struct_set_field_rc(&field_name, value)
819                                .map_err(|message| LustError::RuntimeError { message })?;
820                        }
821
822                        Value::Map(map) => {
823                            use crate::bytecode::ValueKey;
824                            let key = ValueKey::String(field_name.clone());
825                            map.borrow_mut().insert(key, value);
826                        }
827
828                        _ => {
829                            return Err(LustError::RuntimeError {
830                                message: format!(
831                                    "Cannot set field '{}' on {:?}",
832                                    field_name.as_str(),
833                                    object
834                                ),
835                            })
836                        }
837                    }
838
839                    if let Some(key) = invalidate_key {
840                        self.struct_tostring_cache.remove(&key);
841                    }
842                }
843
844                Instruction::Concat(dest, lhs, rhs) => {
845                    let (left, right) = {
846                        let frame =
847                            self.call_stack
848                                .last_mut()
849                                .ok_or_else(|| LustError::RuntimeError {
850                                    message: "Empty call stack".to_string(),
851                                })?;
852                        let left = frame.registers[lhs as usize].clone();
853                        let right = frame.registers[rhs as usize].clone();
854                        (left, right)
855                    };
856                    let left_str = self.value_to_string_for_concat(&left)?;
857                    let right_str = self.value_to_string_for_concat(&right)?;
858                    let mut combined = String::with_capacity(left_str.len() + right_str.len());
859                    combined.push_str(left_str.as_ref());
860                    combined.push_str(right_str.as_ref());
861                    let result = Value::string(combined);
862                    self.set_register(dest, result)?;
863                }
864
865                Instruction::GetIndex(dest, array_reg, index_reg) => {
866                    let collection = self.get_register(array_reg)?;
867                    let index = self.get_register(index_reg)?;
868                    let result = match collection {
869                        Value::Array(arr) => {
870                            let idx = index.as_int().ok_or_else(|| LustError::RuntimeError {
871                                message: "Array index must be an integer".to_string(),
872                            })?;
873                            let borrowed = arr.borrow();
874                            if idx < 0 || idx as usize >= borrowed.len() {
875                                return Err(LustError::RuntimeError {
876                                    message: format!(
877                                        "Array index {} out of bounds (length: {})",
878                                        idx,
879                                        borrowed.len()
880                                    ),
881                                });
882                            }
883
884                            borrowed[idx as usize].clone()
885                        }
886
887                        Value::Map(map) => {
888                            use crate::bytecode::ValueKey;
889                            let key = ValueKey::from_value(index).ok_or_else(|| {
890                                LustError::RuntimeError {
891                                    message: format!(
892                                        "Cannot use {:?} as map key (not hashable)",
893                                        index
894                                    ),
895                                }
896                            })?;
897                            map.borrow().get(&key).cloned().unwrap_or(Value::Nil)
898                        }
899
900                        _ => {
901                            return Err(LustError::RuntimeError {
902                                message: format!("Cannot index {:?}", collection.type_of()),
903                            })
904                        }
905                    };
906                    self.set_register(dest, result)?;
907                }
908
909                Instruction::ArrayLen(dest, array_reg) => {
910                    let collection = self.get_register(array_reg)?;
911                    match collection {
912                        Value::Array(arr) => {
913                            let len = int_from_usize(arr.borrow().len());
914                            self.set_register(dest, Value::Int(len))?;
915                        }
916
917                        _ => {
918                            return Err(LustError::RuntimeError {
919                                message: format!(
920                                    "ArrayLen requires array, got {:?}",
921                                    collection.type_of()
922                                ),
923                            });
924                        }
925                    }
926                }
927
928                Instruction::CallMethod(
929                    obj_reg,
930                    method_name_idx,
931                    first_arg,
932                    arg_count,
933                    dest_reg,
934                ) => {
935                    let object = self.get_register(obj_reg)?.clone();
936                    let method_name = {
937                        let func = &self.functions[self.call_stack.last().unwrap().function_idx];
938                        func.chunk.constants[method_name_idx as usize]
939                            .as_string()
940                            .ok_or_else(|| LustError::RuntimeError {
941                                message: "Method name must be a string".to_string(),
942                            })?
943                            .to_string()
944                    };
945                    if let Value::Struct {
946                        name: struct_name, ..
947                    } = &object
948                    {
949                        let mangled_name = format!("{}:{}", struct_name, method_name);
950                        if let Some(func_idx) =
951                            self.functions.iter().position(|f| f.name == mangled_name)
952                        {
953                            let mut frame = CallFrame {
954                                function_idx: func_idx,
955                                ip: 0,
956                                registers: array::from_fn(|_| Value::Nil),
957                                base_register: 0,
958                                return_dest: Some(dest_reg),
959                                upvalues: Vec::new(),
960                            };
961                            frame.registers[0] = object.clone();
962                            for i in 0..arg_count {
963                                frame.registers[(i + 1) as usize] =
964                                    self.get_register(first_arg + i)?.clone();
965                            }
966
967                            self.call_stack.push(frame);
968                            continue;
969                        }
970                    }
971
972                    let mut args = Vec::new();
973                    for i in 0..arg_count {
974                        args.push(self.get_register(first_arg + i)?.clone());
975                    }
976
977                    let result = self.call_builtin_method(&object, &method_name, args)?;
978                    self.set_register(dest_reg, result)?;
979                }
980
981                Instruction::Closure(dest, func_idx, first_upvalue_reg, upvalue_count) => {
982                    use crate::bytecode::Upvalue;
983                    let mut upvalues = Vec::new();
984                    for i in 0..upvalue_count {
985                        let value = self.get_register(first_upvalue_reg + i)?.clone();
986                        upvalues.push(Upvalue::new(value));
987                    }
988
989                    let closure = Value::Closure {
990                        function_idx: func_idx as usize,
991                        upvalues: Rc::new(upvalues),
992                    };
993                    self.set_register(dest, closure)?;
994                }
995
996                Instruction::LoadUpvalue(dest, upvalue_idx) => {
997                    let frame = self
998                        .call_stack
999                        .last()
1000                        .ok_or_else(|| LustError::RuntimeError {
1001                            message: "Empty call stack".to_string(),
1002                        })?;
1003                    if (upvalue_idx as usize) < frame.upvalues.len() {
1004                        let value = frame.upvalues[upvalue_idx as usize].clone();
1005                        self.set_register(dest, value)?;
1006                    } else {
1007                        return Err(LustError::RuntimeError {
1008                            message: format!(
1009                                "Upvalue index {} out of bounds (have {} upvalues)",
1010                                upvalue_idx,
1011                                frame.upvalues.len()
1012                            ),
1013                        });
1014                    }
1015                }
1016
1017                Instruction::StoreUpvalue(upvalue_idx, src) => {
1018                    let value = self.get_register(src)?.clone();
1019                    let frame =
1020                        self.call_stack
1021                            .last_mut()
1022                            .ok_or_else(|| LustError::RuntimeError {
1023                                message: "Empty call stack".to_string(),
1024                            })?;
1025                    if (upvalue_idx as usize) < frame.upvalues.len() {
1026                        frame.upvalues[upvalue_idx as usize] = value;
1027                    } else {
1028                        return Err(LustError::RuntimeError {
1029                            message: format!(
1030                                "Upvalue index {} out of bounds (have {} upvalues)",
1031                                upvalue_idx,
1032                                frame.upvalues.len()
1033                            ),
1034                        });
1035                    }
1036                }
1037
1038                Instruction::SetIndex(collection_reg, index_reg, value_reg) => {
1039                    let collection = self.get_register(collection_reg)?;
1040                    let index = self.get_register(index_reg)?;
1041                    let value = self.get_register(value_reg)?.clone();
1042                    match collection {
1043                        Value::Array(arr) => {
1044                            let idx = index.as_int().ok_or_else(|| LustError::RuntimeError {
1045                                message: "Array index must be an integer".to_string(),
1046                            })?;
1047                            let mut borrowed = arr.borrow_mut();
1048                            if idx < 0 || idx as usize >= borrowed.len() {
1049                                return Err(LustError::RuntimeError {
1050                                    message: format!(
1051                                        "Array index {} out of bounds (length: {})",
1052                                        idx,
1053                                        borrowed.len()
1054                                    ),
1055                                });
1056                            }
1057
1058                            borrowed[idx as usize] = value;
1059                        }
1060
1061                        Value::Map(map) => {
1062                            use crate::bytecode::ValueKey;
1063                            let key = ValueKey::from_value(index).ok_or_else(|| {
1064                                LustError::RuntimeError {
1065                                    message: format!(
1066                                        "Cannot use {:?} as map key (not hashable)",
1067                                        index
1068                                    ),
1069                                }
1070                            })?;
1071                            map.borrow_mut().insert(key, value);
1072                        }
1073
1074                        _ => {
1075                            return Err(LustError::RuntimeError {
1076                                message: format!("Cannot index {:?}", collection.type_of()),
1077                            })
1078                        }
1079                    }
1080                }
1081
1082                Instruction::TypeIs(dest, value_reg, type_name_idx) => {
1083                    let value = self.get_register(value_reg)?.clone();
1084                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
1085                    let type_name = func.chunk.constants[type_name_idx as usize]
1086                        .as_string()
1087                        .ok_or_else(|| LustError::RuntimeError {
1088                            message: "Type name must be a string".to_string(),
1089                        })?
1090                        .to_string();
1091                    let matches = self.value_is_type(&value, &type_name);
1092                    self.set_register(dest, Value::Bool(matches))?;
1093                }
1094            }
1095
1096            if self.jit.enabled {
1097                if let Some(recorder) = &mut self.trace_recorder {
1098                    if recorder.is_recording() {
1099                        if self.skip_next_trace_record {
1100                            self.skip_next_trace_record = false;
1101                        } else {
1102                            let function = &self.functions[func_idx];
1103                            if let Some(frame) = self.call_stack.last() {
1104                                if let Err(e) = recorder.record_instruction(
1105                                    instruction,
1106                                    ip_before_execution,
1107                                    &frame.registers,
1108                                    function,
1109                                    func_idx,
1110                                ) {
1111                                    crate::jit::log(|| format!("⚠️  JIT: {}", e));
1112                                    self.trace_recorder = None;
1113                                }
1114                            }
1115                        }
1116                    }
1117                }
1118            }
1119        }
1120    }
1121
1122    pub(super) fn binary_op<F>(
1123        &mut self,
1124        dest: Register,
1125        lhs: Register,
1126        rhs: Register,
1127        op: F,
1128    ) -> Result<()>
1129    where
1130        F: FnOnce(&Value, &Value) -> Result<Value>,
1131    {
1132        let left = self.get_register(lhs)?;
1133        let right = self.get_register(rhs)?;
1134        let result = op(left, right)?;
1135        self.set_register(dest, result)
1136    }
1137
1138    pub(super) fn comparison_op<F>(
1139        &mut self,
1140        dest: Register,
1141        lhs: Register,
1142        rhs: Register,
1143        op: F,
1144    ) -> Result<()>
1145    where
1146        F: FnOnce(LustFloat, LustFloat) -> bool,
1147    {
1148        let left = self.get_register(lhs)?;
1149        let right = self.get_register(rhs)?;
1150        let result = match (left, right) {
1151            (Value::Int(a), Value::Int(b)) => op(float_from_int(*a), float_from_int(*b)),
1152            (Value::Float(a), Value::Float(b)) => op(*a, *b),
1153            (Value::Int(a), Value::Float(b)) => op(float_from_int(*a), *b),
1154            (Value::Float(a), Value::Int(b)) => op(*a, float_from_int(*b)),
1155            _ => {
1156                return Err(LustError::RuntimeError {
1157                    message: format!("Cannot compare {:?} and {:?}", left, right),
1158                })
1159            }
1160        };
1161        self.set_register(dest, Value::Bool(result))
1162    }
1163
1164    pub(super) fn value_is_type(&self, value: &Value, type_name: &str) -> bool {
1165        let value_type_name = match value {
1166            Value::Int(_) => "int",
1167            Value::Float(_) => "float",
1168            Value::String(_) => "string",
1169            Value::Bool(_) => "bool",
1170            Value::Nil => "nil",
1171            Value::Array(_) => "Array",
1172            Value::Tuple(_) => "Tuple",
1173            Value::Map(_) => "Map",
1174            Value::Struct { name, .. } => name.as_str(),
1175            Value::WeakStruct(weak) => weak.struct_name(),
1176            Value::Enum { enum_name, .. } => enum_name.as_str(),
1177            Value::Function(_) | Value::NativeFunction(_) | Value::Closure { .. } => "function",
1178            Value::Iterator(_) => "Iterator",
1179            Value::Task(_) => "task",
1180        };
1181        if value_type_name == type_name {
1182            return true;
1183        }
1184
1185        if type_name.starts_with("Array") && matches!(value, Value::Array(_)) {
1186            return true;
1187        }
1188
1189        if type_name.starts_with("Map") && matches!(value, Value::Map(_)) {
1190            return true;
1191        }
1192
1193        if type_name.starts_with("Tuple") && matches!(value, Value::Tuple(_)) {
1194            return true;
1195        }
1196
1197        if type_name == "Option"
1198            && matches!(value, Value::Enum { enum_name, .. } if enum_name == "Option")
1199        {
1200            return true;
1201        }
1202
1203        if type_name == "Result"
1204            && matches!(value, Value::Enum { enum_name, .. } if enum_name == "Result")
1205        {
1206            return true;
1207        }
1208
1209        if type_name == "unknown" {
1210            return true;
1211        }
1212
1213        if let Some(_) = self
1214            .trait_impls
1215            .get(&(value_type_name.to_string(), type_name.to_string()))
1216        {
1217            return true;
1218        }
1219
1220        false
1221    }
1222
1223    pub(super) fn get_register(&self, reg: Register) -> Result<&Value> {
1224        let frame = self
1225            .call_stack
1226            .last()
1227            .ok_or_else(|| LustError::RuntimeError {
1228                message: "Empty call stack".to_string(),
1229            })?;
1230        Ok(&frame.registers[reg as usize])
1231    }
1232
1233    pub(super) fn set_register(&mut self, reg: Register, value: Value) -> Result<()> {
1234        self.observe_value(&value);
1235        let frame = self
1236            .call_stack
1237            .last_mut()
1238            .ok_or_else(|| LustError::RuntimeError {
1239                message: "Empty call stack".to_string(),
1240            })?;
1241        frame.registers[reg as usize] = value;
1242        self.maybe_collect_cycles();
1243        Ok(())
1244    }
1245
1246    pub(super) fn handle_native_call_outcome(
1247        &mut self,
1248        dest: Register,
1249        outcome: NativeCallResult,
1250    ) -> Result<()> {
1251        match outcome {
1252            NativeCallResult::Return(value) => self.set_register(dest, value),
1253            NativeCallResult::Yield(value) => {
1254                if self.current_task.is_some() {
1255                    self.set_register(dest, Value::Nil)?;
1256                    self.pending_task_signal = Some(TaskSignal::Yield { dest, value });
1257                    Ok(())
1258                } else {
1259                    Err(LustError::RuntimeError {
1260                        message: "task.yield() can only be used inside a task".to_string(),
1261                    })
1262                }
1263            }
1264
1265            NativeCallResult::Stop(value) => {
1266                if self.current_task.is_some() {
1267                    self.set_register(dest, Value::Nil)?;
1268                    self.pending_task_signal = Some(TaskSignal::Stop { value });
1269                    Ok(())
1270                } else {
1271                    Err(LustError::RuntimeError {
1272                        message: "task.stop() can only be used inside a task".to_string(),
1273                    })
1274                }
1275            }
1276        }
1277    }
1278
1279    pub fn value_to_string_for_concat(&mut self, value: &Value) -> Result<Rc<String>> {
1280        match value {
1281            Value::String(s) => Ok(s.clone()),
1282            Value::Struct { name, .. } => self.invoke_tostring(value, name),
1283            Value::Enum { enum_name, .. } => self.invoke_tostring(value, enum_name),
1284            _ => Ok(Rc::new(value.to_string())),
1285        }
1286    }
1287
1288    pub fn call_value(&mut self, func: &Value, args: Vec<Value>) -> Result<Value> {
1289        match func {
1290            Value::Function(func_idx) => {
1291                let mut frame = CallFrame {
1292                    function_idx: *func_idx,
1293                    ip: 0,
1294                    registers: array::from_fn(|_| Value::Nil),
1295                    base_register: 0,
1296                    return_dest: None,
1297                    upvalues: Vec::new(),
1298                };
1299                for (i, arg) in args.into_iter().enumerate() {
1300                    frame.registers[i] = arg;
1301                }
1302
1303                let stack_depth_before = self.call_stack.len();
1304                self.call_stack.push(frame);
1305                let previous_target = self.call_until_depth;
1306                self.call_until_depth = Some(stack_depth_before);
1307                let run_result = self.run();
1308                self.call_until_depth = previous_target;
1309                run_result
1310            }
1311
1312            Value::Closure {
1313                function_idx: func_idx,
1314                upvalues,
1315            } => {
1316                let upvalue_values: Vec<Value> = upvalues.iter().map(|uv| uv.get()).collect();
1317                let mut frame = CallFrame {
1318                    function_idx: *func_idx,
1319                    ip: 0,
1320                    registers: array::from_fn(|_| Value::Nil),
1321                    base_register: 0,
1322                    return_dest: None,
1323                    upvalues: upvalue_values,
1324                };
1325                for (i, arg) in args.into_iter().enumerate() {
1326                    frame.registers[i] = arg;
1327                }
1328
1329                let stack_depth_before = self.call_stack.len();
1330                self.call_stack.push(frame);
1331                let previous_target = self.call_until_depth;
1332                self.call_until_depth = Some(stack_depth_before);
1333                let run_result = self.run();
1334                self.call_until_depth = previous_target;
1335                run_result
1336            }
1337
1338            Value::NativeFunction(native_fn) => {
1339                self.push_current_vm();
1340                let outcome = native_fn(&args);
1341                self.pop_current_vm();
1342                let outcome = outcome.map_err(|e| LustError::RuntimeError { message: e })?;
1343                match outcome {
1344                    NativeCallResult::Return(value) => Ok(value),
1345                    NativeCallResult::Yield(_) | NativeCallResult::Stop(_) => {
1346                        Err(LustError::RuntimeError {
1347                            message: "Yielding or stopping is not allowed from this context"
1348                                .to_string(),
1349                        })
1350                    }
1351                }
1352            }
1353
1354            _ => Err(LustError::RuntimeError {
1355                message: format!("Cannot call non-function value: {:?}", func),
1356            }),
1357        }
1358    }
1359}