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