lust/vm/
execution.rs

1use super::*;
2use crate::bytecode::ValueKey;
3use core::{array, ptr};
4impl VM {
5    fn lua_table_map(value: &Value) -> Option<Value> {
6        if let Value::Enum {
7            enum_name,
8            variant,
9            values,
10        } = value
11        {
12            if enum_name == "LuaValue" && variant == "Table" {
13                if let Some(inner) = values.as_ref().and_then(|vals| vals.get(0)) {
14                    if let Some(map) = inner.struct_get_field("table") {
15                        return Some(map);
16                    }
17                }
18            }
19        }
20
21        if let Value::Struct { name, .. } = value {
22            if name == "LuaTable" {
23                if let Some(map) = value.struct_get_field("table") {
24                    return Some(map);
25                }
26            }
27        }
28
29        None
30    }
31
32    fn lua_table_key_value(value: &Value) -> Value {
33        if let Value::Enum {
34            enum_name,
35            variant,
36            values,
37        } = value
38        {
39            if enum_name == "LuaValue" {
40                return match variant.as_str() {
41                    "Nil" => Value::Nil,
42                    "Bool" | "Int" | "Float" | "String" | "Table" | "Function" | "LightUserdata"
43                    | "Userdata" | "Thread" => values
44                        .as_ref()
45                        .and_then(|v| v.get(0))
46                        .cloned()
47                        .unwrap_or(Value::Nil),
48                    _ => value.clone(),
49                };
50            }
51        }
52        value.clone()
53    }
54
55    pub(super) fn push_current_vm(&mut self) {
56        let ptr = self as *mut VM;
57        crate::vm::push_vm_ptr(ptr);
58    }
59
60    pub(super) fn pop_current_vm(&mut self) {
61        crate::vm::pop_vm_ptr();
62    }
63
64    pub(super) fn run(&mut self) -> Result<Value> {
65        loop {
66            if let Some(target_depth) = self.call_until_depth {
67                if self.call_stack.len() == target_depth {
68                    if let Some(return_value) = self.pending_return_value.take() {
69                        self.call_until_depth = None;
70                        return Ok(return_value);
71                    }
72                }
73            }
74
75            if let Some(return_value) = self.pending_return_value.take() {
76                if let Some(dest_reg) = self.pending_return_dest.take() {
77                    self.set_register(dest_reg, return_value)?;
78                }
79            }
80
81            if self.current_task.is_some() {
82                if let Some(signal) = self.pending_task_signal.take() {
83                    self.last_task_signal = Some(signal);
84                    return Ok(Value::Nil);
85                }
86            }
87
88            if self.call_stack.len() > self.max_stack_depth {
89                return Err(LustError::RuntimeError {
90                    message: "Stack overflow".to_string(),
91                });
92            }
93
94            let executing_frame_index =
95                self.call_stack
96                    .len()
97                    .checked_sub(1)
98                    .ok_or_else(|| LustError::RuntimeError {
99                        message: "Empty call stack".to_string(),
100                    })?;
101            let frame = self
102                .call_stack
103                .last_mut()
104                .ok_or_else(|| LustError::RuntimeError {
105                    message: "Empty call stack".to_string(),
106                })?;
107            let (instruction, ip_before_execution, func_idx) = {
108                let func = &self.functions[frame.function_idx];
109                if frame.ip >= func.chunk.instructions.len() {
110                    self.call_stack.pop();
111                    if self.call_stack.is_empty() {
112                        return Ok(Value::Nil);
113                    }
114
115                    continue;
116                }
117
118                let instruction = func.chunk.instructions[frame.ip];
119                frame.ip += 1;
120                let ip_before_execution = frame.ip;
121                let func_idx = frame.function_idx;
122                (instruction, ip_before_execution, func_idx)
123            };
124            let (should_check_jit, loop_start_ip) = if let Instruction::Jump(offset) = instruction {
125                if offset < 0 {
126                    let current_frame = self.call_stack.last().unwrap();
127                    let jump_target = (current_frame.ip as isize + offset as isize) as usize;
128                    (true, jump_target)
129                } else {
130                    (false, 0)
131                }
132            } else {
133                (false, 0)
134            };
135            if should_check_jit && self.jit.enabled {
136                let count = self.jit.profiler.record_backedge(func_idx, loop_start_ip);
137                if let Some(trace_id) = self
138                    .jit
139                    .root_traces
140                    .get(&(func_idx, loop_start_ip))
141                    .copied()
142                {
143                    let frame = self.call_stack.last_mut().unwrap();
144                    let registers_ptr = frame.registers.as_mut_ptr();
145                    let entry = self.jit.get_trace(trace_id).map(|t| t.entry);
146                    if let Some(entry_fn) = entry {
147                        crate::jit::log(|| {
148                            format!(
149                                "▶️  JIT: Executing trace #{} at func {} ip {}",
150                                trace_id.0, func_idx, loop_start_ip
151                            )
152                        });
153
154                        // Capture RSP before and after to detect stack leaks
155                        let rsp_before: usize;
156                        unsafe { std::arch::asm!("mov {}, rsp", out(reg) rsp_before) };
157
158                        let result = entry_fn(registers_ptr, self as *mut VM, ptr::null());
159
160                        let rsp_after: usize;
161                        unsafe { std::arch::asm!("mov {}, rsp", out(reg) rsp_after) };
162
163                        let rsp_diff = rsp_after as isize - rsp_before as isize;
164                        crate::jit::log(|| {
165                            format!("🎯 JIT: Trace #{} execution result: {} (RSP before: {:x}, after: {:x}, diff: {})",
166                            trace_id.0, result, rsp_before, rsp_after, rsp_diff)
167                        });
168
169                        if result == 0 {
170                            if let Some(frame) = self.call_stack.last_mut() {
171                                frame.ip = loop_start_ip;
172                            }
173
174                            continue;
175                        } else if result > 0 {
176                            let guard_index = (result - 1) as usize;
177                            let side_trace_id = self
178                                .jit
179                                .get_trace(trace_id)
180                                .and_then(|t| t.guards.get(guard_index))
181                                .and_then(|g| g.side_trace);
182                            if let Some(side_trace_id) = side_trace_id {
183                                crate::jit::log(|| {
184                                    format!(
185                                        "🌳 JIT: Executing side trace #{} for guard #{}",
186                                        side_trace_id.0, guard_index
187                                    )
188                                });
189                                let frame = self.call_stack.last_mut().unwrap();
190                                let registers_ptr = frame.registers.as_mut_ptr();
191                                let side_entry = self.jit.get_trace(side_trace_id).map(|t| t.entry);
192                                if let Some(side_entry_fn) = side_entry {
193                                    let side_result =
194                                        side_entry_fn(registers_ptr, self as *mut VM, ptr::null());
195                                    if side_result == 0 {
196                                        crate::jit::log(|| {
197                                            format!(
198                                                "✅ JIT: Side trace #{} executed successfully",
199                                                side_trace_id.0
200                                            )
201                                        });
202                                    } else {
203                                        crate::jit::log(|| {
204                                            format!(
205                                                "⚠️  JIT: Side trace #{} failed, falling back to interpreter",
206                                                side_trace_id.0
207                                            )
208                                        });
209                                    }
210                                }
211                            } else {
212                                if let Some(trace) = self.jit.get_trace(trace_id) {
213                                    if let Some(g) = trace.guards.get(guard_index) {
214                                        if g.bailout_ip != 0 {
215                                            continue;
216                                        }
217                                    }
218                                }
219
220                                self.handle_guard_failure(trace_id, guard_index, func_idx)?;
221                                self.jit.root_traces.remove(&(func_idx, loop_start_ip));
222                            }
223                        } else {
224                            crate::jit::log(|| {
225                                "⚠️  JIT: Trace execution failed (unknown error)".to_string()
226                            });
227                            if let Some(frame) = self.call_stack.last_mut() {
228                                frame.ip = loop_start_ip;
229                            }
230
231                            self.jit.root_traces.remove(&(func_idx, loop_start_ip));
232                        }
233                    }
234                } else {
235                    let is_side_trace = self.side_trace_context.is_some();
236                    if is_side_trace {
237                        if let Some(recorder) = &self.trace_recorder {
238                            if !recorder.is_recording() {
239                                crate::jit::log(|| {
240                                    format!(
241                                        "📝 JIT: Trace recording complete - {} ops recorded",
242                                        recorder.trace.ops.len()
243                                    )
244                                });
245                                let recorder = self.trace_recorder.take().unwrap();
246                                let mut trace = recorder.finish();
247                                let side_trace_ctx = self.side_trace_context.take().unwrap();
248                                let mut optimizer = TraceOptimizer::new();
249                                let hoisted_constants = optimizer.optimize(&mut trace);
250                                let (parent_trace_id, guard_index) = side_trace_ctx;
251                                crate::jit::log(|| {
252                                    format!(
253                                        "⚙️  JIT: Compiling side trace (parent: #{}, guard: {})...",
254                                        parent_trace_id.0, guard_index
255                                    )
256                                });
257                                let trace_id = self.jit.alloc_trace_id();
258                                match JitCompiler::new().compile_trace(
259                                    &trace,
260                                    trace_id,
261                                    Some(parent_trace_id),
262                                    hoisted_constants.clone(),
263                                ) {
264                                    Ok(compiled_trace) => {
265                                        crate::jit::log(|| {
266                                            format!(
267                                                "✅ JIT: Side trace #{} compiled successfully!",
268                                                trace_id.0
269                                            )
270                                        });
271                                        if let Some(parent) =
272                                            self.jit.get_trace_mut(parent_trace_id)
273                                        {
274                                            if guard_index < parent.guards.len() {
275                                                parent.guards[guard_index].side_trace =
276                                                    Some(trace_id);
277                                                crate::jit::log(|| {
278                                                    format!(
279                                                        "🔗 JIT: Linked side trace #{} to parent trace #{} guard #{}",
280                                                        trace_id.0, parent_trace_id.0, guard_index
281                                                    )
282                                                });
283                                            }
284                                        }
285
286                                        self.jit.store_side_trace(compiled_trace);
287                                    }
288
289                                    Err(e) => {
290                                        crate::jit::log(|| {
291                                            format!("❌ JIT: Side trace compilation failed: {}", e)
292                                        });
293                                    }
294                                }
295                            }
296                        }
297                    } else {
298                        if let Some(recorder) = &mut self.trace_recorder {
299                            if recorder.is_recording() && count > crate::jit::HOT_THRESHOLD + 1 {
300                                crate::jit::log(|| {
301                                    format!(
302                                        "📝 JIT: Trace recording complete - {} ops recorded",
303                                        recorder.trace.ops.len()
304                                    )
305                                });
306                                let recorder = self.trace_recorder.take().unwrap();
307                                let mut trace = recorder.finish();
308                                let mut optimizer = TraceOptimizer::new();
309                                let hoisted_constants = optimizer.optimize(&mut trace);
310                                crate::jit::log(|| "⚙️  JIT: Compiling root trace...".to_string());
311                                let trace_id = self.jit.alloc_trace_id();
312                                match JitCompiler::new().compile_trace(
313                                    &trace,
314                                    trace_id,
315                                    None,
316                                    hoisted_constants.clone(),
317                                ) {
318                                    Ok(compiled_trace) => {
319                                        crate::jit::log(|| {
320                                            format!(
321                                                "✅ JIT: Trace #{} compiled successfully!",
322                                                trace_id.0
323                                            )
324                                        });
325                                        crate::jit::log(|| {
326                                            "🚀 JIT: Future iterations will use native code!"
327                                                .to_string()
328                                        });
329                                        self.jit.store_root_trace(
330                                            func_idx,
331                                            loop_start_ip,
332                                            compiled_trace,
333                                        );
334                                    }
335
336                                    Err(e) => {
337                                        crate::jit::log(|| {
338                                            format!("❌ JIT: Trace compilation failed: {}", e)
339                                        });
340                                    }
341                                }
342                            }
343                        }
344
345                        if count == crate::jit::HOT_THRESHOLD + 1 {
346                            crate::jit::log(|| {
347                                format!(
348                                    "🔥 JIT: Hot loop detected at func {} ip {} - starting trace recording!",
349                                    func_idx, loop_start_ip
350                                )
351                            });
352                            let mut recorder =
353                                TraceRecorder::new(func_idx, loop_start_ip, MAX_TRACE_LENGTH);
354                            // Specialize loop-invariant values at trace entry
355                            {
356                                let frame = self.call_stack.last().unwrap();
357                                let func = &self.functions[func_idx];
358                                recorder.specialize_trace_inputs(&frame.registers, func);
359                            }
360                            self.trace_recorder = Some(recorder);
361                            self.skip_next_trace_record = true;
362                        }
363                    }
364                }
365            }
366
367            match instruction {
368                Instruction::LoadNil(dest) => {
369                    self.set_register(dest, Value::Nil)?;
370                }
371
372                Instruction::LoadBool(dest, value) => {
373                    self.set_register(dest, Value::Bool(value))?;
374                }
375
376                Instruction::LoadConst(dest, const_idx) => {
377                    let constant = {
378                        let func = &self.functions[func_idx];
379                        func.chunk.constants[const_idx as usize].clone()
380                    };
381                    self.set_register(dest, constant)?;
382                }
383
384                Instruction::LoadGlobal(dest, name_idx) => {
385                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
386                    let name = func.chunk.constants[name_idx as usize]
387                        .as_string()
388                        .ok_or_else(|| LustError::RuntimeError {
389                            message: "Global name must be a string".to_string(),
390                        })?;
391                    if let Some(value) = self.globals.get(name) {
392                        self.set_register(dest, value.clone())?;
393                    } else if let Some(value) = self.natives.get(name) {
394                        self.set_register(dest, value.clone())?;
395                    } else {
396                        if let Some((_, value)) =
397                            self.globals.iter().find(|(key, _)| key.as_str() == name)
398                        {
399                            self.set_register(dest, value.clone())?;
400                        } else if let Some((_, value)) =
401                            self.natives.iter().find(|(key, _)| key.as_str() == name)
402                        {
403                            self.set_register(dest, value.clone())?;
404                        } else {
405                            return Err(LustError::RuntimeError {
406                                message: format!("Undefined global: {}", name),
407                            });
408                        }
409                    }
410                }
411
412                Instruction::StoreGlobal(name_idx, src) => {
413                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
414                    let name = func.chunk.constants[name_idx as usize]
415                        .as_string()
416                        .ok_or_else(|| LustError::RuntimeError {
417                            message: "Global name must be a string".to_string(),
418                        })?;
419                    let value = self.get_register(src)?.clone();
420                    self.globals.insert(name.to_string(), value);
421                }
422
423                Instruction::Move(dest, src) => {
424                    let value = self.get_register(src)?.clone();
425                    self.set_register(dest, value)?;
426                }
427
428                Instruction::Add(dest, lhs, rhs) => {
429                    self.binary_op(dest, lhs, rhs, |l, r| match (l, r) {
430                        (Value::Int(a), Value::Int(b)) => Ok(Value::Int(a + b)),
431                        (Value::Float(a), Value::Float(b)) => Ok(Value::Float(a + b)),
432                        (Value::Int(a), Value::Float(b)) => {
433                            Ok(Value::Float(float_from_int(*a) + *b))
434                        }
435                        (Value::Float(a), Value::Int(b)) => {
436                            Ok(Value::Float(*a + float_from_int(*b)))
437                        }
438                        _ => Err(LustError::RuntimeError {
439                            message: format!("Cannot add {:?} and {:?}", l, r),
440                        }),
441                    })?;
442                }
443
444                Instruction::Sub(dest, lhs, rhs) => {
445                    self.binary_op(dest, lhs, rhs, |l, r| match (l, r) {
446                        (Value::Int(a), Value::Int(b)) => Ok(Value::Int(a - b)),
447                        (Value::Float(a), Value::Float(b)) => Ok(Value::Float(a - b)),
448                        (Value::Int(a), Value::Float(b)) => {
449                            Ok(Value::Float(float_from_int(*a) - *b))
450                        }
451                        (Value::Float(a), Value::Int(b)) => {
452                            Ok(Value::Float(*a - float_from_int(*b)))
453                        }
454                        _ => Err(LustError::RuntimeError {
455                            message: format!("Cannot subtract {:?} and {:?}", l, r),
456                        }),
457                    })?;
458                }
459
460                Instruction::Mul(dest, lhs, rhs) => {
461                    self.binary_op(dest, lhs, rhs, |l, r| match (l, r) {
462                        (Value::Int(a), Value::Int(b)) => Ok(Value::Int(a * b)),
463                        (Value::Float(a), Value::Float(b)) => Ok(Value::Float(a * b)),
464                        (Value::Int(a), Value::Float(b)) => {
465                            Ok(Value::Float(float_from_int(*a) * *b))
466                        }
467                        (Value::Float(a), Value::Int(b)) => {
468                            Ok(Value::Float(*a * float_from_int(*b)))
469                        }
470                        _ => Err(LustError::RuntimeError {
471                            message: format!("Cannot multiply {:?} and {:?}", l, r),
472                        }),
473                    })?;
474                }
475
476                Instruction::Div(dest, lhs, rhs) => {
477                    self.binary_op(dest, lhs, rhs, |l, r| match (l, r) {
478                        (Value::Int(a), Value::Int(b)) => {
479                            if *b == 0 {
480                                Err(LustError::RuntimeError {
481                                    message: "Division by zero".to_string(),
482                                })
483                            } else {
484                                Ok(Value::Int(a / b))
485                            }
486                        }
487
488                        (Value::Float(a), Value::Float(b)) => Ok(Value::Float(*a / *b)),
489                        (Value::Int(a), Value::Float(b)) => {
490                            Ok(Value::Float(float_from_int(*a) / *b))
491                        }
492                        (Value::Float(a), Value::Int(b)) => {
493                            Ok(Value::Float(*a / float_from_int(*b)))
494                        }
495                        _ => Err(LustError::RuntimeError {
496                            message: format!("Cannot divide {:?} and {:?}", l, r),
497                        }),
498                    })?;
499                }
500
501                Instruction::Mod(dest, lhs, rhs) => {
502                    self.binary_op(dest, lhs, rhs, |l, r| match (l, r) {
503                        (Value::Int(a), Value::Int(b)) => {
504                            if *b == 0 {
505                                Err(LustError::RuntimeError {
506                                    message: "Modulo by zero".to_string(),
507                                })
508                            } else {
509                                Ok(Value::Int(a % b))
510                            }
511                        }
512
513                        (Value::Float(a), Value::Float(b)) => {
514                            if *b == 0.0 {
515                                Err(LustError::RuntimeError {
516                                    message: "Modulo by zero".to_string(),
517                                })
518                            } else {
519                                Ok(Value::Float(a % b))
520                            }
521                        }
522
523                        (Value::Int(a), Value::Float(b)) => {
524                            if *b == 0.0 {
525                                Err(LustError::RuntimeError {
526                                    message: "Modulo by zero".to_string(),
527                                })
528                            } else {
529                                Ok(Value::Float(float_from_int(*a) % *b))
530                            }
531                        }
532
533                        (Value::Float(a), Value::Int(b)) => {
534                            if *b == 0 {
535                                Err(LustError::RuntimeError {
536                                    message: "Modulo by zero".to_string(),
537                                })
538                            } else {
539                                Ok(Value::Float(*a % float_from_int(*b)))
540                            }
541                        }
542
543                        _ => Err(LustError::RuntimeError {
544                            message: format!("Cannot modulo {:?} and {:?}", l, r),
545                        }),
546                    })?;
547                }
548
549                Instruction::Neg(dest, src) => {
550                    let value = self.get_register(src)?;
551                    let result = match value {
552                        Value::Int(i) => Value::Int(-i),
553                        Value::Float(f) => Value::Float(-f),
554                        _ => {
555                            return Err(LustError::RuntimeError {
556                                message: format!("Cannot negate {:?}", value),
557                            })
558                        }
559                    };
560                    self.set_register(dest, result)?;
561                }
562
563                Instruction::Eq(dest, lhs, rhs) => {
564                    let left = self.get_register(lhs)?;
565                    let right = self.get_register(rhs)?;
566                    self.set_register(dest, Value::Bool(left == right))?;
567                }
568
569                Instruction::Ne(dest, lhs, rhs) => {
570                    let left = self.get_register(lhs)?;
571                    let right = self.get_register(rhs)?;
572                    self.set_register(dest, Value::Bool(left != right))?;
573                }
574
575                Instruction::Lt(dest, lhs, rhs) => {
576                    self.comparison_op(dest, lhs, rhs, |l, r| l < r)?;
577                }
578
579                Instruction::Le(dest, lhs, rhs) => {
580                    self.comparison_op(dest, lhs, rhs, |l, r| l <= r)?;
581                }
582
583                Instruction::Gt(dest, lhs, rhs) => {
584                    self.comparison_op(dest, lhs, rhs, |l, r| l > r)?;
585                }
586
587                Instruction::Ge(dest, lhs, rhs) => {
588                    self.comparison_op(dest, lhs, rhs, |l, r| l >= r)?;
589                }
590
591                Instruction::And(dest, lhs, rhs) => {
592                    let left = self.get_register(lhs)?;
593                    let right = self.get_register(rhs)?;
594                    let result = Value::Bool(left.is_truthy() && right.is_truthy());
595                    self.set_register(dest, result)?;
596                }
597
598                Instruction::Or(dest, lhs, rhs) => {
599                    let left = self.get_register(lhs)?;
600                    let right = self.get_register(rhs)?;
601                    let result = Value::Bool(left.is_truthy() || right.is_truthy());
602                    self.set_register(dest, result)?;
603                }
604
605                Instruction::Not(dest, src) => {
606                    let value = self.get_register(src)?;
607                    self.set_register(dest, Value::Bool(!value.is_truthy()))?;
608                }
609
610                Instruction::Jump(offset) => {
611                    let frame = self.call_stack.last_mut().unwrap();
612                    frame.ip = (frame.ip as isize + offset as isize) as usize;
613                }
614
615                Instruction::JumpIf(cond, offset) => {
616                    let condition = self.get_register(cond)?;
617                    if condition.is_truthy() {
618                        let frame = self.call_stack.last_mut().unwrap();
619                        frame.ip = (frame.ip as isize + offset as isize) as usize;
620                    }
621                }
622
623                Instruction::JumpIfNot(cond, offset) => {
624                    let condition = self.get_register(cond)?;
625                    if !condition.is_truthy() {
626                        let frame = self.call_stack.last_mut().unwrap();
627                        frame.ip = (frame.ip as isize + offset as isize) as usize;
628                    }
629                }
630
631                Instruction::Call(func_reg, first_arg, arg_count, dest_reg) => {
632                    let mut func_value = self.get_register(func_reg)?.clone();
633                    // if let Value::Enum { enum_name, variant, .. } = &func_value {
634                    //     if enum_name == "LuaValue" && variant == "Table" {
635                    //         eprintln!("DEBUG: Instruction::Call with LuaValue.Table");
636                    //     }
637                    // }
638
639                    // Check if this is a table/userdata with __call metamethod (Lua compat)
640                    let needs_call_value = {
641                        let mut check_value = &func_value;
642                        // Unwrap LuaValue enum if needed
643                        if let Value::Enum { enum_name, variant, values } = &func_value {
644                            if enum_name == "LuaValue" && (variant == "Table" || variant == "Userdata") {
645                                if let Some(inner) = values.as_ref().and_then(|v| v.get(0)) {
646                                    check_value = inner;
647                                }
648                            }
649                        }
650                        // Check if it's a LuaTable/LuaUserdata struct with metamethods
651                        if let Value::Struct { name, .. } = check_value {
652                            (name == "LuaTable" || name == "LuaUserdata") &&
653                            check_value.struct_get_field("metamethods").is_some()
654                        } else {
655                            false
656                        }
657                    };
658
659                    if needs_call_value {
660                        // eprintln!("DEBUG Instruction::Call: Delegating to call_value for table/userdata");
661                        // Delegate to call_value which handles __call metamethods
662                        let mut args = Vec::new();
663                        for i in 0..arg_count {
664                            args.push(self.get_register(first_arg + i)?.clone());
665                        }
666                        let result = self.call_value(&func_value, args)?;
667                        self.set_register(dest_reg, result)?;
668                        continue;
669                    } else {
670                        // Check what type we're actually dealing with
671                        if let Value::Enum { enum_name, variant, .. } = &func_value {
672                            if enum_name == "LuaValue" && (variant == "Table" || variant == "Userdata") {
673                                eprintln!("DEBUG Instruction::Call: Have LuaValue.{} but needs_call_value=false", variant);
674                            }
675                        }
676                    }
677
678                    loop {
679                        let handle = match &func_value {
680                            Value::Enum {
681                                enum_name,
682                                variant,
683                                values,
684                            } if enum_name == "LuaValue" && variant == "Function" => values
685                                .as_ref()
686                                .and_then(|vals| vals.get(0))
687                                .and_then(|v| v.struct_get_field("handle"))
688                                .and_then(|v| v.as_int())
689                                .map(|i| i as usize),
690                            _ => None,
691                        };
692                        let Some(handle) = handle else { break };
693                        let inner = crate::lua_compat::lookup_lust_function(handle).ok_or_else(|| {
694                            LustError::RuntimeError {
695                                message: format!(
696                                    "LuaValue function handle {} was not registered with VM",
697                                    handle
698                                ),
699                            }
700                        })?;
701                        func_value = inner;
702                    }
703                    match func_value {
704                        Value::Function(func_idx) => {
705                            let mut args = Vec::new();
706                            for i in 0..arg_count {
707                                args.push(self.get_register(first_arg + i)?.clone());
708                            }
709
710                            let mut frame = CallFrame {
711                                function_idx: func_idx,
712                                ip: 0,
713                                registers: array::from_fn(|_| Value::Nil),
714                                base_register: 0,
715                                return_dest: Some(dest_reg),
716                                upvalues: Vec::new(),
717                            };
718                            for (i, arg) in args.into_iter().enumerate() {
719                                frame.registers[i] = arg;
720                            }
721
722                            self.call_stack.push(frame);
723                        }
724
725                        Value::Closure {
726                            function_idx: func_idx,
727                            upvalues,
728                        } => {
729                            let mut args = Vec::new();
730                            for i in 0..arg_count {
731                                args.push(self.get_register(first_arg + i)?.clone());
732                            }
733
734                            let upvalue_values: Vec<Value> =
735                                upvalues.iter().map(|uv| uv.get()).collect();
736                            let mut frame = CallFrame {
737                                function_idx: func_idx,
738                                ip: 0,
739                                registers: array::from_fn(|_| Value::Nil),
740                                base_register: 0,
741                                return_dest: Some(dest_reg),
742                                upvalues: upvalue_values,
743                            };
744                            for (i, arg) in args.into_iter().enumerate() {
745                                frame.registers[i] = arg;
746                            }
747
748                            self.call_stack.push(frame);
749                        }
750
751                        Value::NativeFunction(native_fn) => {
752                            let mut args = Vec::new();
753                            for i in 0..arg_count {
754                                args.push(self.get_register(first_arg + i)?.clone());
755                            }
756
757                            self.push_current_vm();
758                            let outcome = native_fn(&args);
759                            self.pop_current_vm();
760                            let outcome =
761                                outcome.map_err(|e| LustError::RuntimeError { message: e })?;
762                            self.handle_native_call_outcome(dest_reg, outcome)?;
763                        }
764
765                        _ => {
766                            return Err(LustError::RuntimeError {
767                                message: format!(
768                                    "Cannot call non-function value: {:?}",
769                                    func_value
770                                ),
771                            })
772                        }
773                    }
774                }
775
776                Instruction::Return(value_reg) => {
777                    let return_value = if value_reg == 255 {
778                        Value::Nil
779                    } else {
780                        self.get_register(value_reg)?.clone()
781                    };
782                    let return_dest = self.call_stack.last().unwrap().return_dest;
783                    self.call_stack.pop();
784                    if self.call_stack.is_empty() {
785                        return Ok(return_value);
786                    }
787
788                    self.pending_return_value = Some(return_value);
789                    self.pending_return_dest = return_dest;
790                }
791
792                Instruction::NewArray(dest, first_elem, count) => {
793                    let mut elements = Vec::new();
794                    for i in 0..count {
795                        elements.push(self.get_register(first_elem + i)?.clone());
796                    }
797
798                    self.set_register(dest, Value::array(elements))?;
799                }
800
801                Instruction::TupleNew(dest, first_elem, count) => {
802                    let mut elements = Vec::new();
803                    for offset in 0..(count as usize) {
804                        let value = self.get_register(first_elem + offset as u8)?.clone();
805                        if let Value::Tuple(existing) = value {
806                            elements.extend(existing.iter().cloned());
807                        } else {
808                            elements.push(value);
809                        }
810                    }
811
812                    self.set_register(dest, Value::tuple(elements))?;
813                }
814
815                Instruction::TupleGet(dest, tuple_reg, index) => {
816                    let tuple_value = self.get_register(tuple_reg)?.clone();
817                    if let Value::Tuple(values) = tuple_value {
818                        let idx = index as usize;
819                        if idx >= values.len() {
820                            return Err(LustError::RuntimeError {
821                                message: format!(
822                                    "Tuple index {} out of bounds (len {})",
823                                    idx,
824                                    values.len()
825                                ),
826                            });
827                        }
828
829                        let value = values[idx].clone();
830                        self.set_register(dest, value)?;
831                    } else {
832                        return Err(LustError::RuntimeError {
833                            message: "Attempted to destructure non-tuple value".to_string(),
834                        });
835                    }
836                }
837
838                Instruction::NewMap(dest) => {
839                    self.set_register(dest, self.new_map_value())?;
840                }
841
842                Instruction::NewStruct(
843                    dest,
844                    name_idx,
845                    first_field_name_idx,
846                    first_field,
847                    field_count,
848                ) => {
849                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
850                    let struct_name = func.chunk.constants[name_idx as usize]
851                        .as_string()
852                        .ok_or_else(|| LustError::RuntimeError {
853                            message: "Struct name must be a string".to_string(),
854                        })?
855                        .to_string();
856                    let mut fields = Vec::with_capacity(field_count as usize);
857                    for i in 0..field_count {
858                        let field_name = func.chunk.constants
859                            [(first_field_name_idx + i as u16) as usize]
860                            .as_string_rc()
861                            .ok_or_else(|| LustError::RuntimeError {
862                                message: "Field name must be a string".to_string(),
863                            })?;
864                        let value = self.get_register(first_field + i)?.clone();
865                        fields.push((field_name, value));
866                    }
867
868                    let struct_value = self.instantiate_struct(&struct_name, fields)?;
869                    self.set_register(dest, struct_value)?;
870                }
871
872                Instruction::NewEnumUnit(dest, enum_name_idx, variant_idx) => {
873                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
874                    let enum_name = func.chunk.constants[enum_name_idx as usize]
875                        .as_string()
876                        .ok_or_else(|| LustError::RuntimeError {
877                            message: "Enum name must be a string".to_string(),
878                        })?
879                        .to_string();
880                    let variant_name = func.chunk.constants[variant_idx as usize]
881                        .as_string()
882                        .ok_or_else(|| LustError::RuntimeError {
883                            message: "Variant name must be a string".to_string(),
884                        })?
885                        .to_string();
886                    self.set_register(dest, Value::enum_unit(enum_name, variant_name))?;
887                }
888
889                Instruction::NewEnumVariant(
890                    dest,
891                    enum_name_idx,
892                    variant_idx,
893                    first_value,
894                    value_count,
895                ) => {
896                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
897                    let enum_name = func.chunk.constants[enum_name_idx as usize]
898                        .as_string()
899                        .ok_or_else(|| LustError::RuntimeError {
900                            message: "Enum name must be a string".to_string(),
901                        })?
902                        .to_string();
903                    let variant_name = func.chunk.constants[variant_idx as usize]
904                        .as_string()
905                        .ok_or_else(|| LustError::RuntimeError {
906                            message: "Variant name must be a string".to_string(),
907                        })?
908                        .to_string();
909                    let mut values = Vec::new();
910                    for i in 0..value_count {
911                        values.push(self.get_register(first_value + i)?.clone());
912                    }
913
914                    self.set_register(dest, Value::enum_variant(enum_name, variant_name, values))?;
915                }
916
917                Instruction::IsEnumVariant(dest, value_reg, enum_name_idx, variant_idx) => {
918                    let value = self.get_register(value_reg)?;
919                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
920                    let enum_name = func.chunk.constants[enum_name_idx as usize]
921                        .as_string()
922                        .ok_or_else(|| LustError::RuntimeError {
923                            message: "Enum name must be a string".to_string(),
924                        })?;
925                    let variant_name = func.chunk.constants[variant_idx as usize]
926                        .as_string()
927                        .ok_or_else(|| LustError::RuntimeError {
928                            message: "Variant name must be a string".to_string(),
929                        })?;
930                    let is_variant = value.is_enum_variant(enum_name, variant_name);
931                    self.set_register(dest, Value::Bool(is_variant))?;
932                }
933
934                Instruction::GetEnumValue(dest, enum_reg, index) => {
935                    let enum_value = self.get_register(enum_reg)?;
936                    if let Some((_, _, Some(values))) = enum_value.as_enum() {
937                        if (index as usize) < values.len() {
938                            self.set_register(dest, values[index as usize].clone())?;
939                        } else {
940                            return Err(LustError::RuntimeError {
941                                message: format!(
942                                    "Enum value index {} out of bounds (has {} values)",
943                                    index,
944                                    values.len()
945                                ),
946                            });
947                        }
948                    } else {
949                        return Err(LustError::RuntimeError {
950                            message: "GetEnumValue requires an enum variant with values"
951                                .to_string(),
952                        });
953                    }
954                }
955
956                Instruction::GetField(dest, obj, field_idx) => {
957                    let object = self.get_register(obj)?;
958                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
959                    let field_name = func.chunk.constants[field_idx as usize]
960                        .as_string_rc()
961                        .ok_or_else(|| LustError::RuntimeError {
962                            message: "Field name must be a string".to_string(),
963                        })?;
964                    let value = if let Some(map_val) = Self::lua_table_map(object) {
965                        if let Value::Map(map) = map_val {
966                            let raw_key_value = Value::String(field_name.clone());
967                            let key = self.make_hash_key(&Self::lua_table_key_value(&raw_key_value))?;
968                            let borrowed = map.borrow();
969                            borrowed.get(&key).cloned().unwrap_or(Value::Nil)
970                        } else {
971                            Value::Nil
972                        }
973                    } else {
974                        match object {
975                            Value::Struct { .. } => object
976                                .struct_get_field_rc(&field_name)
977                                .unwrap_or(Value::Nil),
978                            Value::Map(map) => {
979                                let key = ValueKey::from(field_name.clone());
980                                map.borrow().get(&key).cloned().unwrap_or(Value::Nil)
981                            }
982
983                            _ => {
984                                return Err(LustError::RuntimeError {
985                                    message: format!(
986                                        "Cannot get field '{}' from {:?}",
987                                        field_name.as_str(),
988                                        object
989                                    ),
990                                })
991                            }
992                        }
993                    };
994                    self.set_register(dest, value)?;
995                }
996
997                Instruction::SetField(obj_reg, field_idx, value_reg) => {
998                    let object = self.get_register(obj_reg)?;
999                    let value = self.get_register(value_reg)?.clone();
1000                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
1001                    let field_name = func.chunk.constants[field_idx as usize]
1002                        .as_string_rc()
1003                        .ok_or_else(|| LustError::RuntimeError {
1004                            message: "Field name must be a string".to_string(),
1005                        })?;
1006                    let mut invalidate_key: Option<usize> = None;
1007                    if let Some(map_val) = Self::lua_table_map(object) {
1008                        if let Value::Map(map) = map_val {
1009                            let raw_key_value = Value::String(field_name.clone());
1010                            let key = self.make_hash_key(&Self::lua_table_key_value(&raw_key_value))?;
1011                            map.borrow_mut().insert(key, value);
1012                        } else {
1013                            return Err(LustError::RuntimeError {
1014                                message: format!(
1015                                    "Cannot set field '{}' on {:?}",
1016                                    field_name.as_str(),
1017                                    object
1018                                ),
1019                            });
1020                        }
1021                    } else {
1022                        match object {
1023                            Value::Struct { .. } => {
1024                                invalidate_key = Self::struct_cache_key(object);
1025                                object
1026                                    .struct_set_field_rc(&field_name, value)
1027                                    .map_err(|message| LustError::RuntimeError { message })?;
1028                            }
1029
1030                            Value::Map(map) => {
1031                                let key = ValueKey::from(field_name.clone());
1032                                map.borrow_mut().insert(key, value);
1033                            }
1034
1035                            _ => {
1036                                return Err(LustError::RuntimeError {
1037                                    message: format!(
1038                                        "Cannot set field '{}' on {:?}",
1039                                        field_name.as_str(),
1040                                        object
1041                                    ),
1042                                })
1043                            }
1044                        }
1045                    }
1046
1047                    if let Some(key) = invalidate_key {
1048                        self.struct_tostring_cache.remove(&key);
1049                    }
1050                }
1051
1052                Instruction::Concat(dest, lhs, rhs) => {
1053                    let (left, right) = {
1054                        let frame =
1055                            self.call_stack
1056                                .last_mut()
1057                                .ok_or_else(|| LustError::RuntimeError {
1058                                    message: "Empty call stack".to_string(),
1059                                })?;
1060                        let left = frame.registers[lhs as usize].clone();
1061                        let right = frame.registers[rhs as usize].clone();
1062                        (left, right)
1063                    };
1064                    let left_str = self.value_to_string_for_concat(&left)?;
1065                    let right_str = self.value_to_string_for_concat(&right)?;
1066                    let mut combined = String::with_capacity(left_str.len() + right_str.len());
1067                    combined.push_str(left_str.as_ref());
1068                    combined.push_str(right_str.as_ref());
1069                    let result = Value::string(combined);
1070                    self.set_register(dest, result)?;
1071                }
1072
1073                Instruction::GetIndex(dest, array_reg, index_reg) => {
1074                    let collection = self.get_register(array_reg)?.clone();
1075                    let index = self.get_register(index_reg)?.clone();
1076                    let result = if let Some(map_val) = Self::lua_table_map(&collection) {
1077                        if let Value::Map(map) = map_val {
1078                            let raw_key = self.make_hash_key(&Self::lua_table_key_value(&index))?;
1079                            let borrowed = map.borrow();
1080                            borrowed.get(&raw_key).cloned().unwrap_or(Value::Nil)
1081                        } else {
1082                            return Err(LustError::RuntimeError {
1083                                message: format!("Cannot index {:?}", collection.type_of()),
1084                            });
1085                        }
1086                    } else {
1087                        match collection {
1088                            Value::Array(arr) => {
1089                                let idx = index.as_int().ok_or_else(|| LustError::RuntimeError {
1090                                    message: "Array index must be an integer".to_string(),
1091                                })?;
1092                                let borrowed = arr.borrow();
1093                                if idx < 0 || idx as usize >= borrowed.len() {
1094                                    return Err(LustError::RuntimeError {
1095                                        message: format!(
1096                                            "Array index {} out of bounds (length: {})",
1097                                            idx,
1098                                            borrowed.len()
1099                                        ),
1100                                    });
1101                                }
1102
1103                                borrowed[idx as usize].clone()
1104                            }
1105
1106                            Value::Map(map) => {
1107                                let key = self.make_hash_key(&index)?;
1108                                map.borrow().get(&key).cloned().unwrap_or(Value::Nil)
1109                            }
1110
1111                            _ => {
1112                                return Err(LustError::RuntimeError {
1113                                    message: format!("Cannot index {:?}", collection.type_of()),
1114                                })
1115                            }
1116                        }
1117                    };
1118                    self.set_register(dest, result)?;
1119                }
1120
1121                Instruction::ArrayLen(dest, array_reg) => {
1122                    let collection = self.get_register(array_reg)?;
1123                    match collection {
1124                        Value::Array(arr) => {
1125                            let len = int_from_usize(arr.borrow().len());
1126                            self.set_register(dest, Value::Int(len))?;
1127                        }
1128
1129                        _ => {
1130                            return Err(LustError::RuntimeError {
1131                                message: format!(
1132                                    "ArrayLen requires array, got {:?}",
1133                                    collection.type_of()
1134                                ),
1135                            });
1136                        }
1137                    }
1138                }
1139
1140                Instruction::CallMethod(
1141                    obj_reg,
1142                    method_name_idx,
1143                    first_arg,
1144                    arg_count,
1145                    dest_reg,
1146                ) => {
1147                    let object = self.get_register(obj_reg)?.clone();
1148                    let method_name = {
1149                        let func = &self.functions[self.call_stack.last().unwrap().function_idx];
1150                        func.chunk.constants[method_name_idx as usize]
1151                            .as_string()
1152                            .ok_or_else(|| LustError::RuntimeError {
1153                                message: "Method name must be a string".to_string(),
1154                            })?
1155                            .to_string()
1156                    };
1157                    if let Value::Struct {
1158                        name: struct_name, ..
1159                    } = &object
1160                    {
1161                        let mangled_name = format!("{}:{}", struct_name, method_name);
1162                        if let Some(func_idx) =
1163                            self.functions.iter().position(|f| f.name == mangled_name)
1164                        {
1165                            let mut frame = CallFrame {
1166                                function_idx: func_idx,
1167                                ip: 0,
1168                                registers: array::from_fn(|_| Value::Nil),
1169                                base_register: 0,
1170                                return_dest: Some(dest_reg),
1171                                upvalues: Vec::new(),
1172                            };
1173                            frame.registers[0] = object.clone();
1174                            for i in 0..arg_count {
1175                                frame.registers[(i + 1) as usize] =
1176                                    self.get_register(first_arg + i)?.clone();
1177                            }
1178
1179                            self.call_stack.push(frame);
1180                            continue;
1181                        }
1182
1183                        let mut candidate_names = vec![mangled_name.clone()];
1184                        if let Some(simple) = struct_name.rsplit(|c| c == '.' || c == ':').next() {
1185                            candidate_names.push(format!("{}:{}", simple, method_name));
1186                        }
1187
1188                        let mut handled = false;
1189                        for candidate in candidate_names {
1190                            let mut resolved = None;
1191                            for variant in [candidate.clone(), candidate.replace('.', "::")] {
1192                                if let Some((_name, value)) =
1193                                    self.globals.iter().find(|(name, _)| *name == &variant)
1194                                {
1195                                    resolved = Some(value.clone());
1196                                    break;
1197                                }
1198                                if let Some((_name, value)) =
1199                                    self.natives.iter().find(|(name, _)| *name == &variant)
1200                                {
1201                                    resolved = Some(value.clone());
1202                                    break;
1203                                }
1204                            }
1205
1206                            if let Some(global_func) = resolved {
1207                                let mut call_args = Vec::with_capacity(1 + arg_count as usize);
1208                                call_args.push(object.clone());
1209                                for i in 0..arg_count {
1210                                    call_args.push(self.get_register(first_arg + i)?.clone());
1211                                }
1212                                let result = self.call_value(&global_func, call_args)?;
1213                                self.set_register(dest_reg, result)?;
1214                                handled = true;
1215                                break;
1216                            }
1217                        }
1218                        if handled {
1219                            continue;
1220                        }
1221                    }
1222
1223                    let mut args = Vec::new();
1224                    for i in 0..arg_count {
1225                        args.push(self.get_register(first_arg + i)?.clone());
1226                    }
1227
1228                    let result = self.call_builtin_method(&object, &method_name, args)?;
1229                    self.set_register(dest_reg, result)?;
1230                }
1231
1232                Instruction::Closure(dest, func_idx, first_upvalue_reg, upvalue_count) => {
1233                    use crate::bytecode::Upvalue;
1234                    let mut upvalues = Vec::new();
1235                    for i in 0..upvalue_count {
1236                        let value = self.get_register(first_upvalue_reg + i)?.clone();
1237                        upvalues.push(Upvalue::new(value));
1238                    }
1239
1240                    let closure = Value::Closure {
1241                        function_idx: func_idx as usize,
1242                        upvalues: Rc::new(upvalues),
1243                    };
1244                    self.set_register(dest, closure)?;
1245                }
1246
1247                Instruction::LoadUpvalue(dest, upvalue_idx) => {
1248                    let frame = self
1249                        .call_stack
1250                        .last()
1251                        .ok_or_else(|| LustError::RuntimeError {
1252                            message: "Empty call stack".to_string(),
1253                        })?;
1254                    if (upvalue_idx as usize) < frame.upvalues.len() {
1255                        let value = frame.upvalues[upvalue_idx as usize].clone();
1256                        self.set_register(dest, value)?;
1257                    } else {
1258                        return Err(LustError::RuntimeError {
1259                            message: format!(
1260                                "Upvalue index {} out of bounds (have {} upvalues)",
1261                                upvalue_idx,
1262                                frame.upvalues.len()
1263                            ),
1264                        });
1265                    }
1266                }
1267
1268                Instruction::StoreUpvalue(upvalue_idx, src) => {
1269                    let value = self.get_register(src)?.clone();
1270                    let frame =
1271                        self.call_stack
1272                            .last_mut()
1273                            .ok_or_else(|| LustError::RuntimeError {
1274                                message: "Empty call stack".to_string(),
1275                            })?;
1276                    if (upvalue_idx as usize) < frame.upvalues.len() {
1277                        frame.upvalues[upvalue_idx as usize] = value;
1278                    } else {
1279                        return Err(LustError::RuntimeError {
1280                            message: format!(
1281                                "Upvalue index {} out of bounds (have {} upvalues)",
1282                                upvalue_idx,
1283                                frame.upvalues.len()
1284                            ),
1285                        });
1286                    }
1287                }
1288
1289                Instruction::SetIndex(collection_reg, index_reg, value_reg) => {
1290                    let collection = self.get_register(collection_reg)?.clone();
1291                    let index = self.get_register(index_reg)?.clone();
1292                    let value = self.get_register(value_reg)?.clone();
1293                    if let Some(map_val) = Self::lua_table_map(&collection) {
1294                        if let Value::Map(map) = map_val {
1295                            let key = self.make_hash_key(&Self::lua_table_key_value(&index))?;
1296                            map.borrow_mut().insert(key, value);
1297                        } else {
1298                            return Err(LustError::RuntimeError {
1299                                message: format!("Cannot index {:?}", collection.type_of()),
1300                            });
1301                        }
1302                    } else {
1303                        match collection {
1304                            Value::Array(arr) => {
1305                                let idx = index.as_int().ok_or_else(|| LustError::RuntimeError {
1306                                    message: "Array index must be an integer".to_string(),
1307                                })?;
1308                                let mut borrowed = arr.borrow_mut();
1309                                if idx < 0 || idx as usize >= borrowed.len() {
1310                                    return Err(LustError::RuntimeError {
1311                                        message: format!(
1312                                            "Array index {} out of bounds (length: {})",
1313                                            idx,
1314                                            borrowed.len()
1315                                        ),
1316                                    });
1317                                }
1318
1319                                borrowed[idx as usize] = value;
1320                            }
1321
1322                            Value::Map(map) => {
1323                                let key = self.make_hash_key(&index)?;
1324                                map.borrow_mut().insert(key, value);
1325                            }
1326
1327                            _ => {
1328                                return Err(LustError::RuntimeError {
1329                                    message: format!("Cannot index {:?}", collection.type_of()),
1330                                })
1331                            }
1332                        }
1333                    }
1334                }
1335
1336                Instruction::TypeIs(dest, value_reg, type_name_idx) => {
1337                    let value = self.get_register(value_reg)?.clone();
1338                    let func = &self.functions[self.call_stack.last().unwrap().function_idx];
1339                    let type_name = func.chunk.constants[type_name_idx as usize]
1340                        .as_string()
1341                        .ok_or_else(|| LustError::RuntimeError {
1342                            message: "Type name must be a string".to_string(),
1343                        })?
1344                        .to_string();
1345                    let matches = self.value_is_type(&value, &type_name);
1346                    self.set_register(dest, Value::Bool(matches))?;
1347                }
1348            }
1349
1350            if self.jit.enabled {
1351                if let Some(recorder) = &mut self.trace_recorder {
1352                    if recorder.is_recording() {
1353                        if self.skip_next_trace_record {
1354                            self.skip_next_trace_record = false;
1355                        } else {
1356                            let function = &self.functions[func_idx];
1357                            let registers_opt =
1358                                if let Some(frame) = self.call_stack.get(executing_frame_index) {
1359                                    Some(&frame.registers)
1360                                } else if executing_frame_index > 0 {
1361                                    self.call_stack
1362                                        .get(executing_frame_index - 1)
1363                                        .map(|frame| &frame.registers)
1364                                } else {
1365                                    None
1366                                };
1367                            if let Some(registers) = registers_opt {
1368                                if let Err(e) = recorder.record_instruction(
1369                                    instruction,
1370                                    ip_before_execution,
1371                                    registers,
1372                                    function,
1373                                    func_idx,
1374                                    &self.functions,
1375                                ) {
1376                                    crate::jit::log(|| format!("⚠️  JIT: {}", e));
1377                                    self.trace_recorder = None;
1378                                }
1379                            }
1380                        }
1381                    }
1382                }
1383            }
1384        }
1385    }
1386
1387    pub(super) fn binary_op<F>(
1388        &mut self,
1389        dest: Register,
1390        lhs: Register,
1391        rhs: Register,
1392        op: F,
1393    ) -> Result<()>
1394    where
1395        F: FnOnce(&Value, &Value) -> Result<Value>,
1396    {
1397        let left = self.get_register(lhs)?;
1398        let right = self.get_register(rhs)?;
1399        let result = op(left, right)?;
1400        self.set_register(dest, result)
1401    }
1402
1403    pub(super) fn comparison_op<F>(
1404        &mut self,
1405        dest: Register,
1406        lhs: Register,
1407        rhs: Register,
1408        op: F,
1409    ) -> Result<()>
1410    where
1411        F: FnOnce(LustFloat, LustFloat) -> bool,
1412    {
1413        let left = self.get_register(lhs)?;
1414        let right = self.get_register(rhs)?;
1415        let result = match (left, right) {
1416            (Value::Int(a), Value::Int(b)) => op(float_from_int(*a), float_from_int(*b)),
1417            (Value::Float(a), Value::Float(b)) => op(*a, *b),
1418            (Value::Int(a), Value::Float(b)) => op(float_from_int(*a), *b),
1419            (Value::Float(a), Value::Int(b)) => op(*a, float_from_int(*b)),
1420            _ => {
1421                return Err(LustError::RuntimeError {
1422                    message: format!("Cannot compare {:?} and {:?}", left, right),
1423                })
1424            }
1425        };
1426        self.set_register(dest, Value::Bool(result))
1427    }
1428
1429    pub(super) fn value_is_type(&self, value: &Value, type_name: &str) -> bool {
1430        if let Some(matches) = self.match_function_type(value, type_name) {
1431            return matches;
1432        }
1433
1434        let value_type_name = match value {
1435            Value::Int(_) => "int",
1436            Value::Float(_) => "float",
1437            Value::String(_) => "string",
1438            Value::Bool(_) => "bool",
1439            Value::Nil => "nil",
1440            Value::Array(_) => "Array",
1441            Value::Tuple(_) => "Tuple",
1442            Value::Map(_) => "Map",
1443            Value::Struct { name, .. } => name.as_str(),
1444            Value::WeakStruct(weak) => weak.struct_name(),
1445            Value::Enum { enum_name, .. } => enum_name.as_str(),
1446            Value::Function(_) | Value::NativeFunction(_) | Value::Closure { .. } => "function",
1447            Value::Iterator(_) => "Iterator",
1448            Value::Task(_) => "task",
1449        };
1450        if value_type_name == type_name {
1451            return true;
1452        }
1453
1454        if type_name.starts_with("Array") && matches!(value, Value::Array(_)) {
1455            return true;
1456        }
1457
1458        if type_name.starts_with("Map") && matches!(value, Value::Map(_)) {
1459            return true;
1460        }
1461
1462        if type_name.starts_with("Tuple") && matches!(value, Value::Tuple(_)) {
1463            return true;
1464        }
1465
1466        if type_name == "Option"
1467            && matches!(value, Value::Enum { enum_name, .. } if enum_name == "Option")
1468        {
1469            return true;
1470        }
1471
1472        if type_name == "Result"
1473            && matches!(value, Value::Enum { enum_name, .. } if enum_name == "Result")
1474        {
1475            return true;
1476        }
1477
1478        if type_name == "unknown" {
1479            return true;
1480        }
1481
1482        if let Some(_) = self
1483            .trait_impls
1484            .get(&(value_type_name.to_string(), type_name.to_string()))
1485        {
1486            return true;
1487        }
1488
1489        false
1490    }
1491
1492    fn value_trait_name(&self, value: &Value) -> String {
1493        match value {
1494            Value::Int(_) => "int".to_string(),
1495            Value::Float(_) => "float".to_string(),
1496            Value::String(_) => "string".to_string(),
1497            Value::Bool(_) => "bool".to_string(),
1498            Value::Nil => "nil".to_string(),
1499            Value::Array(_) => "Array".to_string(),
1500            Value::Tuple(_) => "Tuple".to_string(),
1501            Value::Map(_) => "Map".to_string(),
1502            Value::Struct { name, .. } => name.clone(),
1503            Value::WeakStruct(weak) => weak.struct_name().to_string(),
1504            Value::Enum { enum_name, .. } => enum_name.clone(),
1505            Value::Function(_) | Value::NativeFunction(_) | Value::Closure { .. } => {
1506                "function".to_string()
1507            }
1508            Value::Iterator(_) => "Iterator".to_string(),
1509            Value::Task(_) => "task".to_string(),
1510        }
1511    }
1512
1513    fn invoke_hashkey(&mut self, value: &Value, type_name: &str) -> Result<Value> {
1514        let mut candidates = vec![format!("{}:{}", type_name, HASH_KEY_METHOD)];
1515        if let Some(last) = type_name.rsplit('.').next() {
1516            if last != type_name {
1517                candidates.push(format!("{}:{}", last, HASH_KEY_METHOD));
1518            }
1519        }
1520
1521        for candidate in candidates {
1522            if let Some(idx) = self.functions.iter().position(|f| f.name == candidate) {
1523                return self.call_value(&Value::Function(idx), vec![value.clone()]);
1524            }
1525        }
1526
1527        Err(LustError::RuntimeError {
1528            message: format!(
1529                "HashKey trait declared but method '{}' not found for type '{}'",
1530                HASH_KEY_METHOD, type_name
1531            ),
1532        })
1533    }
1534
1535    pub(super) fn make_hash_key(&mut self, value: &Value) -> Result<ValueKey> {
1536        let type_name = self.value_trait_name(value);
1537        if self.type_has_hashkey(&type_name) {
1538            let hashed = self.invoke_hashkey(value, &type_name)?;
1539            Ok(ValueKey::with_hashed(value.clone(), hashed))
1540        } else {
1541            Ok(ValueKey::from_value(value))
1542        }
1543    }
1544
1545    fn match_function_type(&self, value: &Value, type_name: &str) -> Option<bool> {
1546        let wants_signature = type_name.starts_with("function(");
1547        let wants_generic = type_name == "function";
1548        if !wants_signature && !wants_generic {
1549            return None;
1550        }
1551
1552        let matches = match value {
1553            Value::Function(idx) => self.function_signature_matches(*idx, type_name),
1554            Value::Closure { function_idx, .. } => {
1555                self.function_signature_matches(*function_idx, type_name)
1556            }
1557            Value::NativeFunction(_) => wants_generic,
1558            _ => false,
1559        };
1560        Some(matches)
1561    }
1562
1563    fn function_signature_matches(&self, func_idx: usize, type_name: &str) -> bool {
1564        if type_name == "function" {
1565            return true;
1566        }
1567
1568        self.functions
1569            .get(func_idx)
1570            .and_then(|func| func.signature.as_ref())
1571            .map(|signature| signature.to_string() == type_name)
1572            .unwrap_or(false)
1573    }
1574
1575    pub(super) fn get_register(&self, reg: Register) -> Result<&Value> {
1576        let frame = self
1577            .call_stack
1578            .last()
1579            .ok_or_else(|| LustError::RuntimeError {
1580                message: "Empty call stack".to_string(),
1581            })?;
1582        Ok(&frame.registers[reg as usize])
1583    }
1584
1585    pub(super) fn set_register(&mut self, reg: Register, value: Value) -> Result<()> {
1586        self.observe_value(&value);
1587        let frame = self
1588            .call_stack
1589            .last_mut()
1590            .ok_or_else(|| LustError::RuntimeError {
1591                message: "Empty call stack".to_string(),
1592            })?;
1593        frame.registers[reg as usize] = value;
1594        self.maybe_collect_cycles();
1595        Ok(())
1596    }
1597
1598    pub(super) fn handle_native_call_outcome(
1599        &mut self,
1600        dest: Register,
1601        outcome: NativeCallResult,
1602    ) -> Result<()> {
1603        #[cfg(feature = "std")]
1604        if std::env::var_os("LUST_LUA_SOCKET_TRACE").is_some() {
1605            if let NativeCallResult::Return(value) = &outcome {
1606                if let Value::Array(arr) = value {
1607                    let borrowed = arr.borrow();
1608                    let interesting = borrowed.len() > 1
1609                        && matches!(
1610                            borrowed.get(0),
1611                            Some(Value::Enum { enum_name, variant, .. })
1612                                if enum_name == "LuaValue" && variant == "Nil"
1613                        );
1614                    if interesting {
1615                        let func_name = self
1616                            .call_stack
1617                            .last()
1618                            .and_then(|frame| self.functions.get(frame.function_idx))
1619                            .map(|f| f.name.as_str())
1620                            .unwrap_or("<unknown>");
1621                        eprintln!(
1622                            "[lua-socket] native return in {} dest=R{} len={} value={}",
1623                            func_name,
1624                            dest,
1625                            borrowed.len(),
1626                            value
1627                        );
1628                    }
1629                }
1630            }
1631        }
1632        match outcome {
1633            NativeCallResult::Return(value) => self.set_register(dest, value),
1634            NativeCallResult::Yield(value) => {
1635                if self.current_task.is_some() {
1636                    self.set_register(dest, Value::Nil)?;
1637                    self.pending_task_signal = Some(TaskSignal::Yield { dest, value });
1638                    Ok(())
1639                } else {
1640                    Err(LustError::RuntimeError {
1641                        message: "task.yield() can only be used inside a task".to_string(),
1642                    })
1643                }
1644            }
1645
1646            NativeCallResult::Stop(value) => {
1647                if self.current_task.is_some() {
1648                    self.set_register(dest, Value::Nil)?;
1649                    self.pending_task_signal = Some(TaskSignal::Stop { value });
1650                    Ok(())
1651                } else {
1652                    Err(LustError::RuntimeError {
1653                        message: "task.stop() can only be used inside a task".to_string(),
1654                    })
1655                }
1656            }
1657        }
1658    }
1659
1660    pub fn value_to_string_for_concat(&mut self, value: &Value) -> Result<Rc<String>> {
1661        match value {
1662            Value::String(s) => Ok(s.clone()),
1663            Value::Struct { name, .. } => self.invoke_tostring(value, name),
1664            Value::Enum { enum_name, .. } => self.invoke_tostring(value, enum_name),
1665            _ => Ok(Rc::new(value.to_string())),
1666        }
1667    }
1668
1669    #[inline(never)]
1670    pub fn call_value(&mut self, func: &Value, args: Vec<Value>) -> Result<Value> {
1671        // Lua compatibility: honor __call metamethod on Lua tables/userdata.
1672        // Lua semantics: if value has metatable.__call, calling it invokes that function with the
1673        // receiver as the first argument.
1674        let mut args = args;
1675        let maybe_lua_call = {
1676            let mut current = func;
1677            let mut receiver_wrapped = func.clone();
1678
1679            if let Value::Struct { name, .. } = func {
1680                if name == "LuaTable" {
1681                    receiver_wrapped = Value::enum_variant("LuaValue", "Table", vec![func.clone()]);
1682                } else if name == "LuaUserdata" {
1683                    receiver_wrapped =
1684                        Value::enum_variant("LuaValue", "Userdata", vec![func.clone()]);
1685                }
1686            }
1687
1688            if let Value::Enum {
1689                enum_name,
1690                variant,
1691                values,
1692            } = func
1693            {
1694                if enum_name == "LuaValue" && (variant == "Table" || variant == "Userdata") {
1695                    if let Some(inner) = values.as_ref().and_then(|vals| vals.get(0)) {
1696                        current = inner;
1697                    }
1698                }
1699            }
1700
1701            if let Value::Struct { name, .. } = current {
1702                if name == "LuaTable" || name == "LuaUserdata" {
1703                    if let Some(Value::Map(meta_rc)) = current.struct_get_field("metamethods") {
1704                        meta_rc
1705                            .borrow()
1706                            .get(&ValueKey::string("__call".to_string()))
1707                            .cloned()
1708                            .map(|callable| (callable, receiver_wrapped))
1709                    } else {
1710                        None
1711                    }
1712                } else {
1713                    None
1714                }
1715            } else {
1716                None
1717            }
1718        };
1719
1720        if let Some((callable, receiver)) = maybe_lua_call {
1721            // eprintln!("DEBUG: __call metamethod found, invoking with receiver");
1722            let mut call_args = Vec::with_capacity(args.len() + 1);
1723            call_args.push(receiver);
1724            call_args.append(&mut args);
1725            return self.call_value(&callable, call_args);
1726        } else {
1727            // if let Value::Struct { name, .. } = func {
1728            //     if name == "LuaTable" || name == "LuaUserdata" {
1729            //         eprintln!("DEBUG: Calling LuaTable/Userdata but no __call found in metamethods");
1730            //     }
1731            // }
1732        }
1733
1734        match func {
1735            Value::Enum {
1736                enum_name,
1737                variant,
1738                values,
1739            } if enum_name == "LuaValue" && variant == "Function" => {
1740                let handle = values
1741                    .as_ref()
1742                    .and_then(|vals| vals.get(0))
1743                    .and_then(|v| v.struct_get_field("handle"))
1744                    .and_then(|v| v.as_int())
1745                    .map(|i| i as usize)
1746                    .ok_or_else(|| LustError::RuntimeError {
1747                        message: "LuaValue function missing handle".to_string(),
1748                    })?;
1749                let inner = crate::lua_compat::lookup_lust_function(handle).ok_or_else(|| {
1750                    LustError::RuntimeError {
1751                        message: format!(
1752                            "LuaValue function handle {} was not registered with VM",
1753                            handle
1754                        ),
1755                    }
1756                })?;
1757                return self.call_value(&inner, args);
1758            }
1759            Value::Function(func_idx) => {
1760                let saved_pending_return_value = self.pending_return_value.clone();
1761                let saved_pending_return_dest = self.pending_return_dest;
1762                let saved_pending_task_signal = self.pending_task_signal.clone();
1763                let saved_last_task_signal = self.last_task_signal.clone();
1764
1765                let mut frame = CallFrame {
1766                    function_idx: *func_idx,
1767                    ip: 0,
1768                    registers: array::from_fn(|_| Value::Nil),
1769                    base_register: 0,
1770                    return_dest: None,
1771                    upvalues: Vec::new(),
1772                };
1773                for (i, arg) in args.into_iter().enumerate() {
1774                    frame.registers[i] = arg;
1775                }
1776
1777                let stack_depth_before = self.call_stack.len();
1778                self.call_stack.push(frame);
1779                let previous_target = self.call_until_depth;
1780                self.call_until_depth = Some(stack_depth_before);
1781                let run_result = self.run();
1782                self.call_until_depth = previous_target;
1783                match run_result {
1784                    Ok(value) => Ok(value),
1785                    Err(err) => {
1786                        let annotated = self.annotate_runtime_error(err);
1787                        while self.call_stack.len() > stack_depth_before {
1788                            self.call_stack.pop();
1789                        }
1790                        self.pending_return_value = saved_pending_return_value;
1791                        self.pending_return_dest = saved_pending_return_dest;
1792                        self.pending_task_signal = saved_pending_task_signal;
1793                        self.last_task_signal = saved_last_task_signal;
1794                        Err(annotated)
1795                    }
1796                }
1797            }
1798
1799            Value::Closure {
1800                function_idx: func_idx,
1801                upvalues,
1802            } => {
1803                let saved_pending_return_value = self.pending_return_value.clone();
1804                let saved_pending_return_dest = self.pending_return_dest;
1805                let saved_pending_task_signal = self.pending_task_signal.clone();
1806                let saved_last_task_signal = self.last_task_signal.clone();
1807
1808                let upvalue_values: Vec<Value> = upvalues.iter().map(|uv| uv.get()).collect();
1809                let mut frame = CallFrame {
1810                    function_idx: *func_idx,
1811                    ip: 0,
1812                    registers: array::from_fn(|_| Value::Nil),
1813                    base_register: 0,
1814                    return_dest: None,
1815                    upvalues: upvalue_values,
1816                };
1817                for (i, arg) in args.into_iter().enumerate() {
1818                    frame.registers[i] = arg;
1819                }
1820
1821                let stack_depth_before = self.call_stack.len();
1822                self.call_stack.push(frame);
1823                let previous_target = self.call_until_depth;
1824                self.call_until_depth = Some(stack_depth_before);
1825                let run_result = self.run();
1826                self.call_until_depth = previous_target;
1827                match run_result {
1828                    Ok(value) => Ok(value),
1829                    Err(err) => {
1830                        let annotated = self.annotate_runtime_error(err);
1831                        while self.call_stack.len() > stack_depth_before {
1832                            self.call_stack.pop();
1833                        }
1834                        self.pending_return_value = saved_pending_return_value;
1835                        self.pending_return_dest = saved_pending_return_dest;
1836                        self.pending_task_signal = saved_pending_task_signal;
1837                        self.last_task_signal = saved_last_task_signal;
1838                        Err(annotated)
1839                    }
1840                }
1841            }
1842
1843            Value::NativeFunction(native_fn) => {
1844                self.push_current_vm();
1845                let outcome = native_fn(&args);
1846                self.pop_current_vm();
1847                let outcome = outcome.map_err(|e| LustError::RuntimeError { message: e })?;
1848                match outcome {
1849                    NativeCallResult::Return(value) => Ok(value),
1850                    NativeCallResult::Yield(_) | NativeCallResult::Stop(_) => {
1851                        Err(LustError::RuntimeError {
1852                            message: "Yielding or stopping is not allowed from this context"
1853                                .to_string(),
1854                        })
1855                    }
1856                }
1857            }
1858
1859            _ => Err(LustError::RuntimeError {
1860                message: format!("Cannot call non-function value: {:?}", func),
1861            }),
1862        }
1863    }
1864}