1use super::*;
2use crate::bytecode::{LustMap, ValueKey};
3use crate::vm::task::TaskKind;
4use crate::LustInt;
5use alloc::{format, string::ToString};
6use core::{array, cell::RefCell, mem};
7impl VM {
8 pub(super) fn run_task_internal(
9 &mut self,
10 task_id: TaskId,
11 resume_value: Option<Value>,
12 ) -> Result<()> {
13 let mut task = match self.task_manager.detach(task_id) {
14 Some(task) => task,
15 None => {
16 return Err(LustError::RuntimeError {
17 message: format!("Invalid task handle {}", task_id.as_u64()),
18 })
19 }
20 };
21 if matches!(task.kind(), TaskKind::NativeFuture { .. }) {
22 let message = format!(
23 "Task {} is managed by the host runtime and cannot be resumed manually",
24 task_id.as_u64()
25 );
26 self.task_manager.attach(task);
27 return Err(LustError::RuntimeError { message });
28 }
29
30 match task.state {
31 TaskState::Completed | TaskState::Failed | TaskState::Stopped => {
32 let message = format!(
33 "Task {} cannot be resumed (state: {})",
34 task_id.as_u64(),
35 task.state.as_str()
36 );
37 self.task_manager.attach(task);
38 return Err(LustError::RuntimeError { message });
39 }
40
41 TaskState::Running => {
42 self.task_manager.attach(task);
43 return Err(LustError::RuntimeError {
44 message: format!("Task {} is already running", task_id.as_u64()),
45 });
46 }
47
48 _ => {}
49 }
50
51 task.state = TaskState::Running;
52 task.last_yield = None;
53 let mut resume_value_opt = resume_value;
54 if let Some(dest) = task.yield_dest.take() {
55 let value = resume_value_opt.take().unwrap_or(Value::Nil);
56 if let Some(frame) = task.call_stack.last_mut() {
57 frame.registers[dest as usize] = value;
58 }
59 } else if resume_value_opt.is_some() {
60 let message = format!(
61 "Task {} is not waiting for a resume value",
62 task_id.as_u64()
63 );
64 self.task_manager.attach(task);
65 return Err(LustError::RuntimeError { message });
66 }
67
68 mem::swap(&mut self.call_stack, &mut task.call_stack);
69 mem::swap(
70 &mut self.pending_return_value,
71 &mut task.pending_return_value,
72 );
73 mem::swap(&mut self.pending_return_dest, &mut task.pending_return_dest);
74 self.current_task = Some(task_id);
75 self.last_task_signal = None;
76 let run_result = self.run();
77 let signal = self.last_task_signal.take();
78 self.current_task = None;
79 let mut error_result: Option<LustError> = None;
80 match run_result {
81 Ok(value) => {
82 if let Some(signal) = signal {
83 match signal {
84 TaskSignal::Yield {
85 dest,
86 value: yielded,
87 } => {
88 task.state = TaskState::Yielded;
89 task.last_yield = Some(yielded);
90 task.last_result = None;
91 task.yield_dest = Some(dest);
92 }
93
94 TaskSignal::Stop { value: stop_value } => {
95 task.state = TaskState::Stopped;
96 task.last_result = Some(stop_value);
97 task.last_yield = None;
98 task.call_stack.clear();
99 task.pending_return_value = None;
100 task.pending_return_dest = None;
101 }
102 }
103 } else {
104 task.state = TaskState::Completed;
105 task.last_result = Some(value);
106 task.last_yield = None;
107 }
108 }
109
110 Err(err) => {
111 let annotated = self.annotate_runtime_error(err);
112 task.state = TaskState::Failed;
113 task.error = Some(annotated.clone());
114 task.last_yield = None;
115 error_result = Some(annotated);
116 }
117 }
118
119 mem::swap(&mut self.call_stack, &mut task.call_stack);
120 mem::swap(
121 &mut self.pending_return_value,
122 &mut task.pending_return_value,
123 );
124 mem::swap(&mut self.pending_return_dest, &mut task.pending_return_dest);
125 self.task_manager.attach(task);
126 if let Some(err) = error_result {
127 Err(err)
128 } else {
129 Ok(())
130 }
131 }
132
133 pub(super) fn task_id_from_handle(&self, handle: TaskHandle) -> Result<TaskId> {
134 let id = TaskId(handle.id());
135 if self.task_manager.contains(id) {
136 Ok(id)
137 } else {
138 Err(LustError::RuntimeError {
139 message: format!("Invalid task handle {}", handle.id()),
140 })
141 }
142 }
143
144 pub(super) fn prepare_task_frame(
145 &mut self,
146 func: Value,
147 args: Vec<Value>,
148 ) -> Result<CallFrame> {
149 match func {
150 Value::Function(func_idx) => {
151 let function = &self.functions[func_idx];
152 if args.len() != function.param_count as usize {
153 return Err(LustError::RuntimeError {
154 message: format!(
155 "Task entry expects {} arguments, got {}",
156 function.param_count,
157 args.len()
158 ),
159 });
160 }
161
162 let mut frame = CallFrame {
163 function_idx: func_idx,
164 ip: 0,
165 registers: array::from_fn(|_| Value::Nil),
166 base_register: 0,
167 return_dest: None,
168 upvalues: Vec::new(),
169 };
170 for (i, arg) in args.into_iter().enumerate() {
171 frame.registers[i] = arg;
172 }
173
174 Ok(frame)
175 }
176
177 Value::Closure {
178 function_idx,
179 upvalues,
180 } => {
181 let function = &self.functions[function_idx];
182 if args.len() != function.param_count as usize {
183 return Err(LustError::RuntimeError {
184 message: format!(
185 "Task entry expects {} arguments, got {}",
186 function.param_count,
187 args.len()
188 ),
189 });
190 }
191
192 let captured: Vec<Value> = upvalues.iter().map(|uv| uv.get()).collect();
193 let mut frame = CallFrame {
194 function_idx,
195 ip: 0,
196 registers: array::from_fn(|_| Value::Nil),
197 base_register: 0,
198 return_dest: None,
199 upvalues: captured,
200 };
201 for (i, arg) in args.into_iter().enumerate() {
202 frame.registers[i] = arg;
203 }
204
205 Ok(frame)
206 }
207
208 other => Err(LustError::RuntimeError {
209 message: format!("task.run() expects a function or closure, got {:?}", other),
210 }),
211 }
212 }
213
214 pub(super) fn create_task_value(
215 &mut self,
216 func: Value,
217 args: Vec<Value>,
218 ) -> Result<TaskHandle> {
219 let frame = self.prepare_task_frame(func, args)?;
220 let task_id = self.task_manager.next_id();
221 let task = TaskInstance::new(task_id, frame);
222 self.task_manager.insert(task);
223 Ok(task_id.to_handle())
224 }
225
226 pub fn spawn_task_value(&mut self, func: Value, args: Vec<Value>) -> Result<TaskHandle> {
227 let handle = self.create_task_value(func, args)?;
228 let task_id = TaskId(handle.id());
229 if let Err(err) = self.run_task_internal(task_id, None) {
230 let _ = self.task_manager.detach(task_id);
231 return Err(err);
232 }
233
234 Ok(handle)
235 }
236
237 pub fn resume_task_handle(
238 &mut self,
239 handle: TaskHandle,
240 resume_value: Option<Value>,
241 ) -> Result<()> {
242 let task_id = self.task_id_from_handle(handle)?;
243 self.run_task_internal(task_id, resume_value)
244 }
245
246 pub(super) fn stop_task_handle(&mut self, handle: TaskHandle) -> Result<()> {
247 let task_id = self.task_id_from_handle(handle)?;
248 let mut task = match self.task_manager.detach(task_id) {
249 Some(task) => task,
250 None => {
251 return Err(LustError::RuntimeError {
252 message: format!("Invalid task handle {}", handle.id()),
253 })
254 }
255 };
256 match task.state {
257 TaskState::Stopped | TaskState::Completed | TaskState::Failed => {
258 self.task_manager.attach(task);
259 return Ok(());
260 }
261
262 TaskState::Running => {
263 self.task_manager.attach(task);
264 return Err(LustError::RuntimeError {
265 message: format!("Task {} is currently running", handle.id()),
266 });
267 }
268
269 _ => {}
270 }
271
272 task.state = TaskState::Stopped;
273 task.call_stack.clear();
274 task.pending_return_value = None;
275 task.pending_return_dest = None;
276 task.yield_dest = None;
277 task.last_yield = None;
278 self.task_manager.attach(task);
279 Ok(())
280 }
281
282 pub(super) fn restart_task_handle(&mut self, handle: TaskHandle) -> Result<()> {
283 let task_id = self.task_id_from_handle(handle)?;
284 let mut task = match self.task_manager.detach(task_id) {
285 Some(task) => task,
286 None => {
287 return Err(LustError::RuntimeError {
288 message: format!("Invalid task handle {}", handle.id()),
289 })
290 }
291 };
292 task.reset();
293 self.task_manager.insert(task);
294 if let Err(err) = self.run_task_internal(task_id, None) {
295 return Err(err);
296 }
297
298 Ok(())
299 }
300
301 pub fn get_task_instance(&self, handle: TaskHandle) -> Result<&TaskInstance> {
302 let task_id = self.task_id_from_handle(handle)?;
303 self.task_manager
304 .get(task_id)
305 .ok_or_else(|| LustError::RuntimeError {
306 message: format!("Invalid task handle {}", handle.id()),
307 })
308 }
309
310 pub fn current_task_handle(&self) -> Option<TaskHandle> {
311 self.current_task.map(|id| id.to_handle())
312 }
313
314 pub fn create_native_future_task(&mut self) -> TaskHandle {
315 let id = self.task_manager.next_id();
316 let task = TaskInstance::new_native_future(id);
317 let handle = task.handle();
318 self.task_manager.insert(task);
319 handle
320 }
321
322 pub fn complete_native_future_task(
323 &mut self,
324 handle: TaskHandle,
325 outcome: std::result::Result<Value, String>,
326 ) -> Result<()> {
327 let task_id = self.task_id_from_handle(handle)?;
328 let mut task = match self.task_manager.detach(task_id) {
329 Some(task) => task,
330 None => {
331 return Err(LustError::RuntimeError {
332 message: format!("Invalid task handle {}", handle.id()),
333 })
334 }
335 };
336
337 match task.kind_mut() {
338 TaskKind::NativeFuture { .. } => {
339 match outcome {
340 Ok(value) => {
341 task.state = TaskState::Completed;
342 task.last_result = Some(value);
343 task.error = None;
344 }
345 Err(err_msg) => {
346 task.state = TaskState::Failed;
347 task.last_result = None;
348 task.error = Some(LustError::RuntimeError { message: err_msg });
349 }
350 }
351 task.last_yield = None;
352 task.pending_return_value = None;
353 task.pending_return_dest = None;
354 task.yield_dest = None;
355 self.task_manager.attach(task);
356 Ok(())
357 }
358
359 TaskKind::Script => {
360 self.task_manager.attach(task);
361 Err(LustError::RuntimeError {
362 message: "Attempted to complete a script task using native future completion"
363 .to_string(),
364 })
365 }
366 }
367 }
368
369 pub(super) fn call_builtin_method(
370 &mut self,
371 object: &Value,
372 method_name: &str,
373 args: Vec<Value>,
374 ) -> Result<Value> {
375 #[cfg(feature = "std")]
376 if std::env::var_os("LUST_LUA_SOCKET_TRACE").is_some() && method_name == "settimeout" {
377 match object {
378 Value::Enum {
379 enum_name,
380 variant,
381 ..
382 } => {
383 eprintln!(
384 "[lua-socket] CallMethod enum={} variant={} method={}",
385 enum_name, variant, method_name
386 );
387 }
388 other => {
389 eprintln!(
390 "[lua-socket] CallMethod type={:?} method={}",
391 other.type_of(),
392 method_name
393 );
394 }
395 }
396 }
397
398 if let Value::Enum {
399 enum_name,
400 variant,
401 ..
402 } = object
403 {
404 if enum_name == "LuaValue" && variant == "Userdata" {
405 if let Some(result) = self.try_call_lua_dynamic_method(object, method_name, &args)?
406 {
407 return Ok(result);
408 }
409 #[cfg(feature = "std")]
410 if std::env::var_os("LUST_LUA_SOCKET_TRACE").is_some() {
411 let indexer = self.lua_index_metamethod(object);
412 eprintln!(
413 "[lua-socket] userdata missing method '{}' indexer={:?} userdata={:?}",
414 method_name,
415 indexer.as_ref().map(|v| v.type_of()),
416 object
417 );
418 }
419 }
420 }
421
422 if let Value::Struct { name, .. } = object {
423 if name == "LuaTable" {
424 if let Some(result) = self.try_call_lua_dynamic_method(object, method_name, &args)?
425 {
426 return Ok(result);
427 }
428 }
429 }
430
431 if let Value::Enum {
432 enum_name,
433 variant,
434 values,
435 } = object
436 {
437 if enum_name == "LuaValue" && variant == "Table" {
438 if let Some(inner) = values.as_ref().and_then(|vals| vals.get(0)) {
439 return self.call_builtin_method(inner, method_name, args);
440 }
441 }
442 }
443
444 if let Value::Struct {
445 name: struct_name, ..
446 } = object
447 {
448 let mangled_name = format!("{}:{}", struct_name, method_name);
449 if let Some(func_idx) = self.functions.iter().position(|f| f.name == mangled_name) {
450 let mut method_args = vec![object.clone()];
451 method_args.extend(args.clone());
452 return self.call_value(&Value::Function(func_idx), method_args);
453 }
454
455 let mut candidate_names = vec![mangled_name.clone()];
456 if let Some(simple) = struct_name.rsplit(|c| c == '.' || c == ':').next() {
457 candidate_names.push(format!("{}:{}", simple, method_name));
458 }
459
460 for candidate in candidate_names {
461 let mut resolved = None;
462 for variant in [candidate.clone(), candidate.replace('.', "::")] {
463 if let Some(value) = self.get_global(&variant) {
464 resolved = Some(value);
465 break;
466 }
467 }
468
469 if let Some(global_func) = resolved {
470 let mut method_args = vec![object.clone()];
471 method_args.extend(args.clone());
472 return self.call_value(&global_func, method_args);
473 }
474 }
475 }
476
477 match object {
478 Value::Struct { name, .. } if name == "LuaTable" => {
479 let Some(map_rc) = lua_table_map_rc(object) else {
480 return Err(LustError::RuntimeError {
481 message: "LuaTable is missing 'table' map field".to_string(),
482 });
483 };
484 match method_name {
485 "len" => {
486 if !args.is_empty() {
487 return Err(LustError::RuntimeError {
488 message: "len() takes no arguments".to_string(),
489 });
490 }
491 let seq = lua_table_read_sequence(&map_rc.borrow());
492 Ok(Value::Int(seq.len() as LustInt))
493 }
494 "push" => {
495 if args.len() != 1 {
496 return Err(LustError::RuntimeError {
497 message: "push() requires 1 argument (value)".to_string(),
498 });
499 }
500 let value = super::corelib::unwrap_lua_value(args[0].clone());
501 let mut map = map_rc.borrow_mut();
502 let len = lua_table_sequence_len(&map);
503 let key = ValueKey::from_value(&Value::Int((len as LustInt) + 1));
504 map.insert(key, value);
505 Ok(Value::Nil)
506 }
507 "insert" => {
508 if args.len() != 2 {
509 return Err(LustError::RuntimeError {
510 message: "insert() requires 2 arguments (pos, value)".to_string(),
511 });
512 }
513 let pos_raw = super::corelib::unwrap_lua_value(args[0].clone());
514 let pos = pos_raw.as_int().unwrap_or(0).max(1) as usize;
515 let value = super::corelib::unwrap_lua_value(args[1].clone());
516 let mut seq = lua_table_read_sequence(&map_rc.borrow());
517 let idx = pos.saturating_sub(1);
518 if idx > seq.len() {
519 seq.push(value);
520 } else {
521 seq.insert(idx, value);
522 }
523 lua_table_write_sequence(&map_rc, &seq);
524 Ok(Value::Nil)
525 }
526 "remove" => {
527 if args.len() != 1 {
528 return Err(LustError::RuntimeError {
529 message: "remove() requires 1 argument (pos)".to_string(),
530 });
531 }
532 let pos_raw = super::corelib::unwrap_lua_value(args[0].clone());
533 let mut seq = lua_table_read_sequence(&map_rc.borrow());
534 if seq.is_empty() {
535 return Ok(Value::Nil);
536 }
537 let pos = pos_raw.as_int().unwrap_or(seq.len() as LustInt);
538 let idx =
539 ((pos - 1).max(0) as usize).min(seq.len().saturating_sub(1));
540 let removed = seq.remove(idx);
541 lua_table_write_sequence(&map_rc, &seq);
542 Ok(removed)
543 }
544 "concat" => {
545 if args.len() != 3 {
546 return Err(LustError::RuntimeError {
547 message: "concat() requires 3 arguments (sep, i, j)".to_string(),
548 });
549 }
550 let sep_raw = super::corelib::unwrap_lua_value(args[0].clone());
551 let sep = sep_raw.as_string().unwrap_or_default();
552 let seq = lua_table_read_sequence(&map_rc.borrow());
553 let start = super::corelib::unwrap_lua_value(args[1].clone())
554 .as_int()
555 .unwrap_or(1);
556 let end = super::corelib::unwrap_lua_value(args[2].clone())
557 .as_int()
558 .unwrap_or(seq.len() as LustInt);
559 let start_idx = (start - 1).max(0) as usize;
560 let end_idx = end.max(0) as usize;
561 let mut pieces: Vec<String> = Vec::new();
562 for (i, val) in seq.iter().enumerate() {
563 if i < start_idx || i >= end_idx {
564 continue;
565 }
566 let raw = super::corelib::unwrap_lua_value(val.clone());
567 pieces.push(format!("{}", raw));
568 }
569 Ok(Value::string(pieces.join(&sep)))
570 }
571 "unpack" => {
572 if args.len() != 2 {
573 return Err(LustError::RuntimeError {
574 message: "unpack() requires 2 arguments (i, j)".to_string(),
575 });
576 }
577 let unpack = super::stdlib::create_table_unpack_fn();
578 let Value::NativeFunction(func) = unpack else {
579 return Err(LustError::RuntimeError {
580 message: "unpack() builtin is not a native function".to_string(),
581 });
582 };
583 let call_args = vec![object.clone(), args[0].clone(), args[1].clone()];
584 match func(&call_args).map_err(|e| LustError::RuntimeError { message: e })? {
585 NativeCallResult::Return(value) => Ok(value),
586 NativeCallResult::Yield(_) => Err(LustError::RuntimeError {
587 message: "unpack() unexpectedly yielded".to_string(),
588 }),
589 NativeCallResult::Stop(_) => Err(LustError::RuntimeError {
590 message: "unpack() unexpectedly stopped execution".to_string(),
591 }),
592 }
593 }
594 "sort" => {
595 if args.len() != 1 {
596 return Err(LustError::RuntimeError {
597 message: "sort() requires 1 argument (comp)".to_string(),
598 });
599 }
600 let mut seq = lua_table_read_sequence(&map_rc.borrow());
601 seq.sort_by(|a, b| {
602 let la = format!("{}", super::corelib::unwrap_lua_value(a.clone()));
603 let lb = format!("{}", super::corelib::unwrap_lua_value(b.clone()));
604 la.cmp(&lb)
605 });
606 lua_table_write_sequence(&map_rc, &seq);
607 Ok(Value::Nil)
608 }
609 "maxn" => {
610 if !args.is_empty() {
611 return Err(LustError::RuntimeError {
612 message: "maxn() takes no arguments".to_string(),
613 });
614 }
615 let map = map_rc.borrow();
616 let mut max_idx: LustInt = 0;
617 for key in map.keys() {
618 if let Value::Int(i) = key.to_value() {
619 if i > max_idx && i > 0 {
620 max_idx = i;
621 }
622 }
623 }
624 Ok(Value::Int(max_idx))
625 }
626 _ => Err(LustError::RuntimeError {
627 message: format!("LuaTable has no method '{}'", method_name),
628 }),
629 }
630 }
631 Value::Enum {
632 enum_name,
633 variant,
634 values,
635 } if enum_name == "Option" => match method_name {
636 "is_some" => Ok(Value::Bool(variant == "Some")),
637 "is_none" => Ok(Value::Bool(variant == "None")),
638 "unwrap" => {
639 if variant == "Some" {
640 if let Some(vals) = values {
641 if !vals.is_empty() {
642 Ok(vals[0].clone())
643 } else {
644 Err(LustError::RuntimeError {
645 message: "Option::Some has no value".to_string(),
646 })
647 }
648 } else {
649 Err(LustError::RuntimeError {
650 message: "Option::Some has no value".to_string(),
651 })
652 }
653 } else {
654 Err(LustError::RuntimeError {
655 message: "Called unwrap() on Option::None".to_string(),
656 })
657 }
658 }
659
660 "unwrap_or" => {
661 if args.is_empty() {
662 return Err(LustError::RuntimeError {
663 message: "unwrap_or requires a default value".to_string(),
664 });
665 }
666
667 if variant == "Some" {
668 if let Some(vals) = values {
669 if !vals.is_empty() {
670 Ok(vals[0].clone())
671 } else {
672 Ok(args[0].clone())
673 }
674 } else {
675 Ok(args[0].clone())
676 }
677 } else {
678 Ok(args[0].clone())
679 }
680 }
681
682 _ => Err(LustError::RuntimeError {
683 message: format!("Option has no method '{}'", method_name),
684 }),
685 },
686 Value::Enum {
687 enum_name,
688 variant,
689 values,
690 } if enum_name == "Result" => match method_name {
691 "is_ok" => Ok(Value::Bool(variant == "Ok")),
692 "is_err" => Ok(Value::Bool(variant == "Err")),
693 "unwrap" => {
694 if variant == "Ok" {
695 if let Some(vals) = values {
696 if !vals.is_empty() {
697 Ok(vals[0].clone())
698 } else {
699 Err(LustError::RuntimeError {
700 message: "Result::Ok has no value".to_string(),
701 })
702 }
703 } else {
704 Err(LustError::RuntimeError {
705 message: "Result::Ok has no value".to_string(),
706 })
707 }
708 } else {
709 Err(LustError::RuntimeError {
710 message: "Called unwrap() on Result::Err".to_string(),
711 })
712 }
713 }
714
715 "unwrap_or" => {
716 if args.is_empty() {
717 return Err(LustError::RuntimeError {
718 message: "unwrap_or requires a default value".to_string(),
719 });
720 }
721
722 if variant == "Ok" {
723 if let Some(vals) = values {
724 if !vals.is_empty() {
725 Ok(vals[0].clone())
726 } else {
727 Ok(args[0].clone())
728 }
729 } else {
730 Ok(args[0].clone())
731 }
732 } else {
733 Ok(args[0].clone())
734 }
735 }
736
737 _ => Err(LustError::RuntimeError {
738 message: format!("Result has no method '{}'", method_name),
739 }),
740 },
741 Value::Array(arr) => match method_name {
742 "iter" => {
743 let items = arr.borrow().clone();
744 let iter = crate::bytecode::value::IteratorState::Array { items, index: 0 };
745 Ok(Value::Iterator(Rc::new(RefCell::new(iter))))
746 }
747
748 "len" => Ok(Value::Int(int_from_usize(arr.borrow().len()))),
749 "get" => {
750 if args.is_empty() {
751 return Err(LustError::RuntimeError {
752 message: "get requires an index argument".to_string(),
753 });
754 }
755
756 let index = args[0].as_int().ok_or_else(|| LustError::RuntimeError {
757 message: "Array index must be an integer".to_string(),
758 })?;
759 let borrowed = arr.borrow();
760 if index < 0 || index as usize >= borrowed.len() {
761 Ok(Value::none())
762 } else {
763 Ok(Value::some(borrowed[index as usize].clone()))
764 }
765 }
766
767 "first" => {
768 let borrowed = arr.borrow();
769 if borrowed.is_empty() {
770 Ok(Value::none())
771 } else {
772 Ok(Value::some(borrowed[0].clone()))
773 }
774 }
775
776 "last" => {
777 let borrowed = arr.borrow();
778 if borrowed.is_empty() {
779 Ok(Value::none())
780 } else {
781 Ok(Value::some(borrowed[borrowed.len() - 1].clone()))
782 }
783 }
784
785 "push" => {
786 if args.is_empty() {
787 return Err(LustError::RuntimeError {
788 message: "push requires a value argument".to_string(),
789 });
790 }
791
792 arr.borrow_mut().push(args[0].clone());
793 Ok(Value::Nil)
794 }
795
796 "pop" => {
797 let popped = arr.borrow_mut().pop();
798 match popped {
799 Some(val) => Ok(Value::some(val)),
800 None => Ok(Value::none()),
801 }
802 }
803
804 "map" => {
805 if args.is_empty() {
806 return Err(LustError::RuntimeError {
807 message: "map requires a function argument".to_string(),
808 });
809 }
810
811 let func = &args[0];
812 let borrowed = arr.borrow();
813 let mut result = Vec::new();
814 for elem in borrowed.iter() {
815 let mapped_value = self.call_value(func, vec![elem.clone()])?;
816 result.push(mapped_value);
817 }
818
819 Ok(Value::array(result))
820 }
821
822 "filter" => {
823 if args.is_empty() {
824 return Err(LustError::RuntimeError {
825 message: "filter requires a function argument".to_string(),
826 });
827 }
828
829 let func = &args[0];
830 let borrowed = arr.borrow();
831 let mut result = Vec::new();
832 for elem in borrowed.iter() {
833 let keep = self.call_value(func, vec![elem.clone()])?;
834 if keep.is_truthy() {
835 result.push(elem.clone());
836 }
837 }
838
839 Ok(Value::array(result))
840 }
841
842 "reduce" => {
843 if args.len() < 2 {
844 return Err(LustError::RuntimeError {
845 message: "reduce requires an initial value and function".to_string(),
846 });
847 }
848
849 let init_value = &args[0];
850 let func = &args[1];
851 let borrowed = arr.borrow();
852 let mut accumulator = init_value.clone();
853 for elem in borrowed.iter() {
854 accumulator = self.call_value(func, vec![accumulator, elem.clone()])?;
855 }
856
857 Ok(accumulator)
858 }
859
860 "slice" => {
861 if args.len() < 2 {
862 return Err(LustError::RuntimeError {
863 message: "slice requires start and end indices".to_string(),
864 });
865 }
866
867 let start = args[0].as_int().ok_or_else(|| LustError::RuntimeError {
868 message: "Start index must be an integer".to_string(),
869 })? as usize;
870 let end = args[1].as_int().ok_or_else(|| LustError::RuntimeError {
871 message: "End index must be an integer".to_string(),
872 })? as usize;
873 let borrowed = arr.borrow();
874 if start > borrowed.len() || end > borrowed.len() || start > end {
875 return Err(LustError::RuntimeError {
876 message: "Invalid slice indices".to_string(),
877 });
878 }
879
880 let sliced = borrowed[start..end].to_vec();
881 Ok(Value::array(sliced))
882 }
883
884 "clear" => {
885 arr.borrow_mut().clear();
886 Ok(Value::Nil)
887 }
888
889 "is_empty" => Ok(Value::Bool(arr.borrow().is_empty())),
890 _ => Err(LustError::RuntimeError {
891 message: format!("Array has no method '{}'", method_name),
892 }),
893 },
894 Value::String(s) => match method_name {
895 "iter" => {
896 let items: Vec<Value> =
897 s.chars().map(|c| Value::string(c.to_string())).collect();
898 let iter = crate::bytecode::value::IteratorState::Array { items, index: 0 };
899 Ok(Value::Iterator(Rc::new(RefCell::new(iter))))
900 }
901
902 "len" => Ok(Value::Int(int_from_usize(s.len()))),
903 "substring" => {
904 if args.len() < 2 {
905 return Err(LustError::RuntimeError {
906 message: "substring requires start and end indices".to_string(),
907 });
908 }
909
910 let start = args[0].as_int().ok_or_else(|| LustError::RuntimeError {
911 message: "Start index must be an integer".to_string(),
912 })? as usize;
913 let end = args[1].as_int().ok_or_else(|| LustError::RuntimeError {
914 message: "End index must be an integer".to_string(),
915 })? as usize;
916 if start > s.len() || end > s.len() || start > end {
917 return Err(LustError::RuntimeError {
918 message: "Invalid substring indices".to_string(),
919 });
920 }
921
922 Ok(Value::string(&s[start..end]))
923 }
924
925 "find" => {
926 if args.is_empty() {
927 return Err(LustError::RuntimeError {
928 message: "find requires a search string".to_string(),
929 });
930 }
931
932 let search = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
933 message: "Search string must be a string".to_string(),
934 })?;
935 match s.find(search) {
936 Some(pos) => Ok(Value::some(Value::Int(int_from_usize(pos)))),
937 None => Ok(Value::none()),
938 }
939 }
940
941 "starts_with" => {
942 if args.is_empty() {
943 return Err(LustError::RuntimeError {
944 message: "starts_with requires a prefix string".to_string(),
945 });
946 }
947
948 let prefix = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
949 message: "Prefix must be a string".to_string(),
950 })?;
951 Ok(Value::Bool(s.starts_with(prefix)))
952 }
953
954 "ends_with" => {
955 if args.is_empty() {
956 return Err(LustError::RuntimeError {
957 message: "ends_with requires a suffix string".to_string(),
958 });
959 }
960
961 let suffix = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
962 message: "Suffix must be a string".to_string(),
963 })?;
964 Ok(Value::Bool(s.ends_with(suffix)))
965 }
966
967 "split" => {
968 if args.is_empty() {
969 return Err(LustError::RuntimeError {
970 message: "split requires a separator string".to_string(),
971 });
972 }
973
974 let separator = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
975 message: "Separator must be a string".to_string(),
976 })?;
977 let parts: Vec<Value> =
978 s.split(separator).map(|part| Value::string(part)).collect();
979 Ok(Value::array(parts))
980 }
981
982 "trim" => Ok(Value::string(s.trim())),
983 "trim_start" => Ok(Value::string(s.trim_start())),
984 "trim_end" => Ok(Value::string(s.trim_end())),
985 "replace" => {
986 if args.len() < 2 {
987 return Err(LustError::RuntimeError {
988 message: "replace requires 'from' and 'to' string arguments"
989 .to_string(),
990 });
991 }
992
993 let from = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
994 message: "First argument must be a string".to_string(),
995 })?;
996 let to = args[1].as_string().ok_or_else(|| LustError::RuntimeError {
997 message: "Second argument must be a string".to_string(),
998 })?;
999 Ok(Value::string(&s.replace(from, to)))
1000 }
1001
1002 "to_upper" => Ok(Value::string(&s.to_uppercase())),
1003 "to_lower" => Ok(Value::string(&s.to_lowercase())),
1004 "contains" => {
1005 if args.is_empty() {
1006 return Err(LustError::RuntimeError {
1007 message: "contains requires a search string".to_string(),
1008 });
1009 }
1010
1011 let search = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
1012 message: "Search string must be a string".to_string(),
1013 })?;
1014 Ok(Value::Bool(s.contains(search)))
1015 }
1016
1017 "is_empty" => Ok(Value::Bool(s.is_empty())),
1018 "chars" => {
1019 let chars: Vec<Value> =
1020 s.chars().map(|c| Value::string(&c.to_string())).collect();
1021 Ok(Value::array(chars))
1022 }
1023
1024 "lines" => {
1025 let lines: Vec<Value> = s.lines().map(|line| Value::string(line)).collect();
1026 Ok(Value::array(lines))
1027 }
1028
1029 _ => Err(LustError::RuntimeError {
1030 message: format!("String has no method '{}'", method_name),
1031 }),
1032 },
1033 Value::Map(map) => {
1034 use crate::bytecode::ValueKey;
1035 match method_name {
1036 "iter" => {
1037 let items: Vec<(ValueKey, Value)> = map
1038 .borrow()
1039 .iter()
1040 .map(|(k, v)| (k.clone(), v.clone()))
1041 .collect();
1042 let iter =
1043 crate::bytecode::value::IteratorState::MapPairs { items, index: 0 };
1044 return Ok(Value::Iterator(Rc::new(RefCell::new(iter))));
1045 }
1046
1047 "len" => Ok(Value::Int(int_from_usize(map.borrow().len()))),
1048 "get" => {
1049 if args.is_empty() {
1050 return Err(LustError::RuntimeError {
1051 message: "get requires a key argument".to_string(),
1052 });
1053 }
1054
1055 let key = self.make_hash_key(&args[0])?;
1056 match map.borrow().get(&key) {
1057 Some(value) => Ok(Value::some(value.clone())),
1058 None => Ok(Value::none()),
1059 }
1060 }
1061
1062 "set" => {
1063 if args.len() < 2 {
1064 return Err(LustError::RuntimeError {
1065 message: "set requires key and value arguments".to_string(),
1066 });
1067 }
1068
1069 let key = self.make_hash_key(&args[0])?;
1070 let value = args[1].clone();
1071 map.borrow_mut().insert(key, value);
1072 Ok(Value::Nil)
1073 }
1074
1075 "has" => {
1076 if args.is_empty() {
1077 return Err(LustError::RuntimeError {
1078 message: "has requires a key argument".to_string(),
1079 });
1080 }
1081
1082 let key = self.make_hash_key(&args[0])?;
1083 Ok(Value::Bool(map.borrow().contains_key(&key)))
1084 }
1085
1086 "delete" => {
1087 if args.is_empty() {
1088 return Err(LustError::RuntimeError {
1089 message: "delete requires a key argument".to_string(),
1090 });
1091 }
1092
1093 let key = self.make_hash_key(&args[0])?;
1094 match map.borrow_mut().remove(&key) {
1095 Some(value) => Ok(Value::some(value)),
1096 None => Ok(Value::none()),
1097 }
1098 }
1099
1100 "keys" => {
1101 let keys: Vec<Value> = map.borrow().keys().map(|k| k.to_value()).collect();
1102 Ok(Value::array(keys))
1103 }
1104
1105 "values" => {
1106 let values: Vec<Value> = map.borrow().values().cloned().collect();
1107 Ok(Value::array(values))
1108 }
1109
1110 _ => Err(LustError::RuntimeError {
1111 message: format!("Map has no method '{}'", method_name),
1112 }),
1113 }
1114 }
1115
1116 Value::Iterator(state_rc) => match method_name {
1117 "iter" => Ok(Value::Iterator(state_rc.clone())),
1118 "next" => {
1119 use crate::bytecode::value::IteratorState;
1120 let mut state = state_rc.borrow_mut();
1121 match &mut *state {
1122 IteratorState::Array { items, index } => {
1123 if *index < items.len() {
1124 let v = items[*index].clone();
1125 *index += 1;
1126 Ok(Value::some(v))
1127 } else {
1128 Ok(Value::none())
1129 }
1130 }
1131
1132 IteratorState::MapPairs { items, index } => {
1133 if *index < items.len() {
1134 let (k, v) = items[*index].clone();
1135 *index += 1;
1136 Ok(Value::some(Value::array(vec![k.to_value(), v])))
1137 } else {
1138 Ok(Value::none())
1139 }
1140 }
1141 }
1142 }
1143
1144 _ => Err(LustError::RuntimeError {
1145 message: format!("Iterator has no method '{}'", method_name),
1146 }),
1147 },
1148 Value::Float(f) => match method_name {
1149 "to_int" => {
1150 if !args.is_empty() {
1151 return Err(LustError::RuntimeError {
1152 message: "to_int() takes no arguments".to_string(),
1153 });
1154 }
1155
1156 Ok(Value::Int(int_from_float(*f)))
1157 }
1158
1159 "floor" => {
1160 if !args.is_empty() {
1161 return Err(LustError::RuntimeError {
1162 message: "floor() takes no arguments".to_string(),
1163 });
1164 }
1165
1166 Ok(Value::Float(float_floor(*f)))
1167 }
1168
1169 "ceil" => {
1170 if !args.is_empty() {
1171 return Err(LustError::RuntimeError {
1172 message: "ceil() takes no arguments".to_string(),
1173 });
1174 }
1175
1176 Ok(Value::Float(float_ceil(*f)))
1177 }
1178
1179 "round" => {
1180 if !args.is_empty() {
1181 return Err(LustError::RuntimeError {
1182 message: "round() takes no arguments".to_string(),
1183 });
1184 }
1185
1186 Ok(Value::Float(float_round(*f)))
1187 }
1188
1189 "sqrt" => {
1190 if !args.is_empty() {
1191 return Err(LustError::RuntimeError {
1192 message: "sqrt() takes no arguments".to_string(),
1193 });
1194 }
1195
1196 if *f < 0.0 {
1197 return Err(LustError::RuntimeError {
1198 message: "sqrt() requires a non-negative number".to_string(),
1199 });
1200 }
1201
1202 Ok(Value::Float(float_sqrt(*f)))
1203 }
1204
1205 "abs" => {
1206 if !args.is_empty() {
1207 return Err(LustError::RuntimeError {
1208 message: "abs() takes no arguments".to_string(),
1209 });
1210 }
1211
1212 Ok(Value::Float(float_abs(*f)))
1213 }
1214
1215 "min" => {
1216 if args.len() != 1 {
1217 return Err(LustError::RuntimeError {
1218 message: "min() requires 1 argument (other)".to_string(),
1219 });
1220 }
1221 let other = args[0]
1222 .as_float()
1223 .or_else(|| args[0].as_int().map(float_from_int))
1224 .ok_or_else(|| LustError::RuntimeError {
1225 message: "min() other must be a number".to_string(),
1226 })?;
1227 Ok(Value::Float(f.min(other)))
1228 }
1229
1230 "max" => {
1231 if args.len() != 1 {
1232 return Err(LustError::RuntimeError {
1233 message: "max() requires 1 argument (other)".to_string(),
1234 });
1235 }
1236 let other = args[0]
1237 .as_float()
1238 .or_else(|| args[0].as_int().map(float_from_int))
1239 .ok_or_else(|| LustError::RuntimeError {
1240 message: "max() other must be a number".to_string(),
1241 })?;
1242 Ok(Value::Float(f.max(other)))
1243 }
1244
1245 "clamp" => {
1246 if args.len() != 2 {
1247 return Err(LustError::RuntimeError {
1248 message: "clamp() requires 2 arguments (min, max)".to_string(),
1249 });
1250 }
1251
1252 let min = args[0].as_float().ok_or_else(|| LustError::RuntimeError {
1253 message: "clamp() min must be a number".to_string(),
1254 })?;
1255 let max = args[1].as_float().ok_or_else(|| LustError::RuntimeError {
1256 message: "clamp() max must be a number".to_string(),
1257 })?;
1258 if min > max {
1259 return Err(LustError::RuntimeError {
1260 message: "clamp() min must be less than or equal to max".to_string(),
1261 });
1262 }
1263
1264 Ok(Value::Float(float_clamp(*f, min, max)))
1265 }
1266
1267 _ => Err(LustError::RuntimeError {
1268 message: format!("Float has no method '{}'", method_name),
1269 }),
1270 },
1271 Value::Int(i) => match method_name {
1272 "to_float" => {
1273 if !args.is_empty() {
1274 return Err(LustError::RuntimeError {
1275 message: "to_float() takes no arguments".to_string(),
1276 });
1277 }
1278
1279 Ok(Value::Float(float_from_int(*i)))
1280 }
1281
1282 "abs" => {
1283 if !args.is_empty() {
1284 return Err(LustError::RuntimeError {
1285 message: "abs() takes no arguments".to_string(),
1286 });
1287 }
1288
1289 Ok(Value::Int(i.abs()))
1290 }
1291
1292 "min" => {
1293 if args.len() != 1 {
1294 return Err(LustError::RuntimeError {
1295 message: "min() requires 1 argument (other)".to_string(),
1296 });
1297 }
1298 if let Some(other) = args[0].as_int() {
1299 return Ok(Value::Int((*i).min(other)));
1300 }
1301 if let Some(other) = args[0].as_float() {
1302 return Ok(Value::Float(float_from_int(*i).min(other)));
1303 }
1304 Err(LustError::RuntimeError {
1305 message: "min() other must be a number".to_string(),
1306 })
1307 }
1308
1309 "max" => {
1310 if args.len() != 1 {
1311 return Err(LustError::RuntimeError {
1312 message: "max() requires 1 argument (other)".to_string(),
1313 });
1314 }
1315 if let Some(other) = args[0].as_int() {
1316 return Ok(Value::Int((*i).max(other)));
1317 }
1318 if let Some(other) = args[0].as_float() {
1319 return Ok(Value::Float(float_from_int(*i).max(other)));
1320 }
1321 Err(LustError::RuntimeError {
1322 message: "max() other must be a number".to_string(),
1323 })
1324 }
1325
1326 "clamp" => {
1327 if args.len() != 2 {
1328 return Err(LustError::RuntimeError {
1329 message: "clamp() requires 2 arguments (min, max)".to_string(),
1330 });
1331 }
1332
1333 let min = args[0].as_int().ok_or_else(|| LustError::RuntimeError {
1334 message: "clamp() min must be an integer".to_string(),
1335 })?;
1336 let max = args[1].as_int().ok_or_else(|| LustError::RuntimeError {
1337 message: "clamp() max must be an integer".to_string(),
1338 })?;
1339 if min > max {
1340 return Err(LustError::RuntimeError {
1341 message: "clamp() min must be less than or equal to max".to_string(),
1342 });
1343 }
1344
1345 Ok(Value::Int((*i).clamp(min, max)))
1346 }
1347
1348 _ => Err(LustError::RuntimeError {
1349 message: format!("Int has no method '{}'", method_name),
1350 }),
1351 },
1352 _ => Err(LustError::RuntimeError {
1353 message: format!(
1354 "Type {:?} has no method '{}'",
1355 object.type_of(),
1356 method_name
1357 ),
1358 }),
1359 }
1360 }
1361
1362 fn try_call_lua_dynamic_method(
1363 &mut self,
1364 receiver: &Value,
1365 method_name: &str,
1366 args: &[Value],
1367 ) -> Result<Option<Value>> {
1368 let key = Value::string(method_name.to_string());
1369 let method = self.lua_resolve_index(receiver, &key, 8)?;
1370 if matches!(method, Value::Nil) {
1371 return Ok(None);
1372 }
1373
1374 let mut call_args = Vec::with_capacity(1 + args.len());
1375 call_args.push(receiver.clone());
1376 call_args.extend_from_slice(args);
1377 let result = self.call_value(&method, call_args)?;
1378 Ok(Some(result))
1379 }
1380
1381 fn lua_resolve_index(&mut self, receiver: &Value, key: &Value, depth: usize) -> Result<Value> {
1382 if depth == 0 {
1383 return Ok(Value::Nil);
1384 }
1385
1386 if let Some(direct) = self.lua_direct_index(receiver, key) {
1387 if !matches!(direct, Value::Nil) {
1388 return Ok(direct);
1389 }
1390 }
1391
1392 let Some(indexer) = self.lua_index_metamethod(receiver) else {
1393 return Ok(Value::Nil);
1394 };
1395 if matches!(indexer, Value::Nil) {
1396 return Ok(Value::Nil);
1397 }
1398
1399 let is_callable = matches!(
1400 indexer,
1401 Value::Function(_) | Value::Closure { .. } | Value::NativeFunction(_)
1402 ) || matches!(
1403 &indexer,
1404 Value::Enum {
1405 enum_name,
1406 variant,
1407 ..
1408 } if enum_name == "LuaValue" && variant == "Function"
1409 );
1410
1411 if is_callable {
1412 self.call_value(&indexer, vec![receiver.clone(), key.clone()])
1413 } else {
1414 self.lua_resolve_index(&indexer, key, depth - 1)
1415 }
1416 }
1417
1418 fn lua_direct_index(&self, receiver: &Value, key: &Value) -> Option<Value> {
1419 if let Value::Enum {
1420 enum_name,
1421 variant,
1422 values,
1423 } = receiver
1424 {
1425 if enum_name == "LuaValue" && variant == "Table" {
1426 if let Some(inner) = values.as_ref().and_then(|vals| vals.get(0)) {
1427 return self.lua_direct_index(inner, key);
1428 }
1429 }
1430 }
1431
1432 match receiver {
1433 Value::Struct { name, .. } if name == "LuaTable" => {
1434 let Some(Value::Map(map_rc)) = receiver.struct_get_field("table") else {
1435 return None;
1436 };
1437 let raw_key = super::corelib::unwrap_lua_value(key.clone());
1438 let lookup_key = ValueKey::from_value(&raw_key);
1439 let value = map_rc.borrow().get(&lookup_key).cloned();
1440 value
1441 }
1442 Value::Map(map_rc) => {
1443 let raw_key = super::corelib::unwrap_lua_value(key.clone());
1444 let lookup_key = ValueKey::from_value(&raw_key);
1445 let value = map_rc.borrow().get(&lookup_key).cloned();
1446 value
1447 }
1448 _ => None,
1449 }
1450 }
1451
1452 fn lua_index_metamethod(&self, receiver: &Value) -> Option<Value> {
1453 if let Value::Enum {
1454 enum_name,
1455 variant,
1456 values,
1457 } = receiver
1458 {
1459 if enum_name == "LuaValue" && variant == "Table" {
1460 if let Some(inner) = values.as_ref().and_then(|vals| vals.get(0)) {
1461 return self.lua_index_metamethod(inner);
1462 }
1463 }
1464 if enum_name == "LuaValue" && variant == "Userdata" {
1465 if let Some(inner) = values.as_ref().and_then(|vals| vals.get(0)) {
1466 return self.lua_index_metamethod(inner);
1467 }
1468 }
1469 }
1470
1471 let Value::Struct { name, .. } = receiver else {
1472 return None;
1473 };
1474 let Some(Value::Map(meta_rc)) = receiver.struct_get_field("metamethods") else {
1475 return None;
1476 };
1477 if name != "LuaTable" && name != "LuaUserdata" {
1478 return None;
1479 }
1480 let value = meta_rc
1481 .borrow()
1482 .get(&ValueKey::string("__index".to_string()))
1483 .cloned();
1484 value
1485 }
1486}
1487
1488fn lua_table_map_rc(table: &Value) -> Option<Rc<RefCell<LustMap>>> {
1489 match table.struct_get_field("table") {
1490 Some(Value::Map(map_rc)) => Some(map_rc),
1491 _ => None,
1492 }
1493}
1494
1495fn lua_table_sequence_len(map: &LustMap) -> usize {
1496 let mut idx: LustInt = 1;
1497 loop {
1498 let key = ValueKey::from_value(&Value::Int(idx));
1499 if map.contains_key(&key) {
1500 idx += 1;
1501 } else {
1502 break;
1503 }
1504 }
1505 (idx - 1) as usize
1506}
1507
1508fn lua_table_read_sequence(map: &LustMap) -> Vec<Value> {
1509 let mut seq: Vec<Value> = Vec::new();
1510 let mut idx: LustInt = 1;
1511 loop {
1512 let key = ValueKey::from_value(&Value::Int(idx));
1513 if let Some(val) = map.get(&key) {
1514 seq.push(val.clone());
1515 idx += 1;
1516 } else {
1517 break;
1518 }
1519 }
1520 seq
1521}
1522
1523fn lua_table_write_sequence(map_rc: &Rc<RefCell<LustMap>>, seq: &[Value]) {
1524 let mut map = map_rc.borrow_mut();
1525 let mut idx: LustInt = 1;
1526 loop {
1527 let key = ValueKey::from_value(&Value::Int(idx));
1528 if map.remove(&key).is_some() {
1529 idx += 1;
1530 } else {
1531 break;
1532 }
1533 }
1534 for (i, val) in seq.iter().enumerate() {
1535 let key = ValueKey::from_value(&Value::Int((i as LustInt) + 1));
1536 map.insert(key, val.clone());
1537 }
1538}