lust/vm/
execution.rs

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