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 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 {
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 let needs_call_value = {
641 let mut check_value = &func_value;
642 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 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 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 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 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 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 }
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}