1use super::*;
2use alloc::{format, string::ToString};
3use core::{array, cell::RefCell, mem};
4impl VM {
5 pub(super) fn run_task_internal(
6 &mut self,
7 task_id: TaskId,
8 resume_value: Option<Value>,
9 ) -> Result<()> {
10 let mut task = match self.task_manager.detach(task_id) {
11 Some(task) => task,
12 None => {
13 return Err(LustError::RuntimeError {
14 message: format!("Invalid task handle {}", task_id.as_u64()),
15 })
16 }
17 };
18 match task.state {
19 TaskState::Completed | TaskState::Failed | TaskState::Stopped => {
20 let message = format!(
21 "Task {} cannot be resumed (state: {})",
22 task_id.as_u64(),
23 task.state.as_str()
24 );
25 self.task_manager.attach(task);
26 return Err(LustError::RuntimeError { message });
27 }
28
29 TaskState::Running => {
30 self.task_manager.attach(task);
31 return Err(LustError::RuntimeError {
32 message: format!("Task {} is already running", task_id.as_u64()),
33 });
34 }
35
36 _ => {}
37 }
38
39 task.state = TaskState::Running;
40 task.last_yield = None;
41 let mut resume_value_opt = resume_value;
42 if let Some(dest) = task.yield_dest.take() {
43 let value = resume_value_opt.take().unwrap_or(Value::Nil);
44 if let Some(frame) = task.call_stack.last_mut() {
45 frame.registers[dest as usize] = value;
46 }
47 } else if resume_value_opt.is_some() {
48 let message = format!(
49 "Task {} is not waiting for a resume value",
50 task_id.as_u64()
51 );
52 self.task_manager.attach(task);
53 return Err(LustError::RuntimeError { message });
54 }
55
56 mem::swap(&mut self.call_stack, &mut task.call_stack);
57 mem::swap(
58 &mut self.pending_return_value,
59 &mut task.pending_return_value,
60 );
61 mem::swap(&mut self.pending_return_dest, &mut task.pending_return_dest);
62 self.current_task = Some(task_id);
63 self.last_task_signal = None;
64 let run_result = self.run();
65 let signal = self.last_task_signal.take();
66 self.current_task = None;
67 let mut error_result: Option<LustError> = None;
68 match run_result {
69 Ok(value) => {
70 if let Some(signal) = signal {
71 match signal {
72 TaskSignal::Yield {
73 dest,
74 value: yielded,
75 } => {
76 task.state = TaskState::Yielded;
77 task.last_yield = Some(yielded);
78 task.last_result = None;
79 task.yield_dest = Some(dest);
80 }
81
82 TaskSignal::Stop { value: stop_value } => {
83 task.state = TaskState::Stopped;
84 task.last_result = Some(stop_value);
85 task.last_yield = None;
86 task.call_stack.clear();
87 task.pending_return_value = None;
88 task.pending_return_dest = None;
89 }
90 }
91 } else {
92 task.state = TaskState::Completed;
93 task.last_result = Some(value);
94 task.last_yield = None;
95 }
96 }
97
98 Err(err) => {
99 let annotated = self.annotate_runtime_error(err);
100 task.state = TaskState::Failed;
101 task.error = Some(annotated.clone());
102 task.last_yield = None;
103 error_result = Some(annotated);
104 }
105 }
106
107 mem::swap(&mut self.call_stack, &mut task.call_stack);
108 mem::swap(
109 &mut self.pending_return_value,
110 &mut task.pending_return_value,
111 );
112 mem::swap(&mut self.pending_return_dest, &mut task.pending_return_dest);
113 self.task_manager.attach(task);
114 if let Some(err) = error_result {
115 Err(err)
116 } else {
117 Ok(())
118 }
119 }
120
121 pub(super) fn task_id_from_handle(&self, handle: TaskHandle) -> Result<TaskId> {
122 let id = TaskId(handle.id());
123 if self.task_manager.contains(id) {
124 Ok(id)
125 } else {
126 Err(LustError::RuntimeError {
127 message: format!("Invalid task handle {}", handle.id()),
128 })
129 }
130 }
131
132 pub(super) fn prepare_task_frame(
133 &mut self,
134 func: Value,
135 args: Vec<Value>,
136 ) -> Result<CallFrame> {
137 match func {
138 Value::Function(func_idx) => {
139 let function = &self.functions[func_idx];
140 if args.len() != function.param_count as usize {
141 return Err(LustError::RuntimeError {
142 message: format!(
143 "Task entry expects {} arguments, got {}",
144 function.param_count,
145 args.len()
146 ),
147 });
148 }
149
150 let mut frame = CallFrame {
151 function_idx: func_idx,
152 ip: 0,
153 registers: array::from_fn(|_| Value::Nil),
154 base_register: 0,
155 return_dest: None,
156 upvalues: Vec::new(),
157 };
158 for (i, arg) in args.into_iter().enumerate() {
159 frame.registers[i] = arg;
160 }
161
162 Ok(frame)
163 }
164
165 Value::Closure {
166 function_idx,
167 upvalues,
168 } => {
169 let function = &self.functions[function_idx];
170 if args.len() != function.param_count as usize {
171 return Err(LustError::RuntimeError {
172 message: format!(
173 "Task entry expects {} arguments, got {}",
174 function.param_count,
175 args.len()
176 ),
177 });
178 }
179
180 let captured: Vec<Value> = upvalues.iter().map(|uv| uv.get()).collect();
181 let mut frame = CallFrame {
182 function_idx,
183 ip: 0,
184 registers: array::from_fn(|_| Value::Nil),
185 base_register: 0,
186 return_dest: None,
187 upvalues: captured,
188 };
189 for (i, arg) in args.into_iter().enumerate() {
190 frame.registers[i] = arg;
191 }
192
193 Ok(frame)
194 }
195
196 other => Err(LustError::RuntimeError {
197 message: format!("task.run() expects a function or closure, got {:?}", other),
198 }),
199 }
200 }
201
202 pub(super) fn create_task_value(
203 &mut self,
204 func: Value,
205 args: Vec<Value>,
206 ) -> Result<TaskHandle> {
207 let frame = self.prepare_task_frame(func, args)?;
208 let task_id = self.task_manager.next_id();
209 let task = TaskInstance::new(task_id, frame);
210 self.task_manager.insert(task);
211 Ok(task_id.to_handle())
212 }
213
214 pub fn spawn_task_value(&mut self, func: Value, args: Vec<Value>) -> Result<TaskHandle> {
215 let handle = self.create_task_value(func, args)?;
216 let task_id = TaskId(handle.id());
217 if let Err(err) = self.run_task_internal(task_id, None) {
218 let _ = self.task_manager.detach(task_id);
219 return Err(err);
220 }
221
222 Ok(handle)
223 }
224
225 pub fn resume_task_handle(
226 &mut self,
227 handle: TaskHandle,
228 resume_value: Option<Value>,
229 ) -> Result<()> {
230 let task_id = self.task_id_from_handle(handle)?;
231 self.run_task_internal(task_id, resume_value)
232 }
233
234 pub(super) fn stop_task_handle(&mut self, handle: TaskHandle) -> Result<()> {
235 let task_id = self.task_id_from_handle(handle)?;
236 let mut task = match self.task_manager.detach(task_id) {
237 Some(task) => task,
238 None => {
239 return Err(LustError::RuntimeError {
240 message: format!("Invalid task handle {}", handle.id()),
241 })
242 }
243 };
244 match task.state {
245 TaskState::Stopped | TaskState::Completed | TaskState::Failed => {
246 self.task_manager.attach(task);
247 return Ok(());
248 }
249
250 TaskState::Running => {
251 self.task_manager.attach(task);
252 return Err(LustError::RuntimeError {
253 message: format!("Task {} is currently running", handle.id()),
254 });
255 }
256
257 _ => {}
258 }
259
260 task.state = TaskState::Stopped;
261 task.call_stack.clear();
262 task.pending_return_value = None;
263 task.pending_return_dest = None;
264 task.yield_dest = None;
265 task.last_yield = None;
266 self.task_manager.attach(task);
267 Ok(())
268 }
269
270 pub(super) fn restart_task_handle(&mut self, handle: TaskHandle) -> Result<()> {
271 let task_id = self.task_id_from_handle(handle)?;
272 let mut task = match self.task_manager.detach(task_id) {
273 Some(task) => task,
274 None => {
275 return Err(LustError::RuntimeError {
276 message: format!("Invalid task handle {}", handle.id()),
277 })
278 }
279 };
280 task.reset();
281 self.task_manager.insert(task);
282 if let Err(err) = self.run_task_internal(task_id, None) {
283 return Err(err);
284 }
285
286 Ok(())
287 }
288
289 pub fn get_task_instance(&self, handle: TaskHandle) -> Result<&TaskInstance> {
290 let task_id = self.task_id_from_handle(handle)?;
291 self.task_manager
292 .get(task_id)
293 .ok_or_else(|| LustError::RuntimeError {
294 message: format!("Invalid task handle {}", handle.id()),
295 })
296 }
297
298 pub fn current_task_handle(&self) -> Option<TaskHandle> {
299 self.current_task.map(|id| id.to_handle())
300 }
301
302 pub(super) fn call_builtin_method(
303 &mut self,
304 object: &Value,
305 method_name: &str,
306 args: Vec<Value>,
307 ) -> Result<Value> {
308 if let Value::Struct {
309 name: struct_name, ..
310 } = object
311 {
312 let mangled_name = format!("{}:{}", struct_name, method_name);
313 if let Some(func_idx) = self.functions.iter().position(|f| f.name == mangled_name) {
314 let mut method_args = vec![object.clone()];
315 method_args.extend(args);
316 return self.call_value(&Value::Function(func_idx), method_args);
317 }
318 }
319
320 if method_name == "as" {
321 if args.is_empty() {
322 return Err(LustError::RuntimeError {
323 message: ":as() requires a type name argument".to_string(),
324 });
325 }
326
327 let type_name = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
328 message: ":as() type argument must be a string".to_string(),
329 })?;
330 let matches = match (object, type_name) {
331 (Value::Int(_), "int") => true,
332 (Value::Float(_), "float") => true,
333 (Value::String(_), "string") => true,
334 (Value::Bool(_), "bool") => true,
335 (Value::Nil, "nil") => true,
336 (Value::Array(_), t) if t.starts_with("Array") => true,
337 (Value::Map(_), t) if t.starts_with("Map") => true,
338 (Value::Table(_), "Table") => true,
339 (Value::Struct { name, .. }, t) => {
340 if name == t {
341 true
342 } else {
343 self.trait_impls
344 .contains_key(&(name.clone(), t.to_string()))
345 }
346 }
347
348 (Value::Enum { enum_name, .. }, t) => {
349 if enum_name == t || t.starts_with(enum_name) {
350 true
351 } else {
352 self.trait_impls
353 .contains_key(&(enum_name.clone(), t.to_string()))
354 }
355 }
356
357 (Value::Function(_), "function") => true,
358 (Value::NativeFunction(_), "function") => true,
359 (Value::Closure { .. }, "function") => true,
360 (_, "unknown") => true,
361 _ => false,
362 };
363 if matches {
364 return Ok(Value::some(object.clone()));
365 } else {
366 return Ok(Value::none());
367 }
368 }
369
370 match object {
371 Value::Enum {
372 enum_name,
373 variant,
374 values,
375 } if enum_name == "Option" => match method_name {
376 "is_some" => Ok(Value::Bool(variant == "Some")),
377 "is_none" => Ok(Value::Bool(variant == "None")),
378 "unwrap" => {
379 if variant == "Some" {
380 if let Some(vals) = values {
381 if !vals.is_empty() {
382 Ok(vals[0].clone())
383 } else {
384 Err(LustError::RuntimeError {
385 message: "Option::Some has no value".to_string(),
386 })
387 }
388 } else {
389 Err(LustError::RuntimeError {
390 message: "Option::Some has no value".to_string(),
391 })
392 }
393 } else {
394 Err(LustError::RuntimeError {
395 message: "Called unwrap() on Option::None".to_string(),
396 })
397 }
398 }
399
400 "unwrap_or" => {
401 if args.is_empty() {
402 return Err(LustError::RuntimeError {
403 message: "unwrap_or requires a default value".to_string(),
404 });
405 }
406
407 if variant == "Some" {
408 if let Some(vals) = values {
409 if !vals.is_empty() {
410 Ok(vals[0].clone())
411 } else {
412 Ok(args[0].clone())
413 }
414 } else {
415 Ok(args[0].clone())
416 }
417 } else {
418 Ok(args[0].clone())
419 }
420 }
421
422 _ => Err(LustError::RuntimeError {
423 message: format!("Option has no method '{}'", method_name),
424 }),
425 },
426 Value::Enum {
427 enum_name,
428 variant,
429 values,
430 } if enum_name == "Result" => match method_name {
431 "is_ok" => Ok(Value::Bool(variant == "Ok")),
432 "is_err" => Ok(Value::Bool(variant == "Err")),
433 "unwrap" => {
434 if variant == "Ok" {
435 if let Some(vals) = values {
436 if !vals.is_empty() {
437 Ok(vals[0].clone())
438 } else {
439 Err(LustError::RuntimeError {
440 message: "Result::Ok has no value".to_string(),
441 })
442 }
443 } else {
444 Err(LustError::RuntimeError {
445 message: "Result::Ok has no value".to_string(),
446 })
447 }
448 } else {
449 Err(LustError::RuntimeError {
450 message: "Called unwrap() on Result::Err".to_string(),
451 })
452 }
453 }
454
455 "unwrap_or" => {
456 if args.is_empty() {
457 return Err(LustError::RuntimeError {
458 message: "unwrap_or requires a default value".to_string(),
459 });
460 }
461
462 if variant == "Ok" {
463 if let Some(vals) = values {
464 if !vals.is_empty() {
465 Ok(vals[0].clone())
466 } else {
467 Ok(args[0].clone())
468 }
469 } else {
470 Ok(args[0].clone())
471 }
472 } else {
473 Ok(args[0].clone())
474 }
475 }
476
477 _ => Err(LustError::RuntimeError {
478 message: format!("Result has no method '{}'", method_name),
479 }),
480 },
481 Value::Array(arr) => match method_name {
482 "iter" => {
483 let items = arr.borrow().clone();
484 let iter = crate::bytecode::value::IteratorState::Array { items, index: 0 };
485 Ok(Value::Iterator(Rc::new(RefCell::new(iter))))
486 }
487
488 "len" => Ok(Value::Int(int_from_usize(arr.borrow().len()))),
489 "get" => {
490 if args.is_empty() {
491 return Err(LustError::RuntimeError {
492 message: "get requires an index argument".to_string(),
493 });
494 }
495
496 let index = args[0].as_int().ok_or_else(|| LustError::RuntimeError {
497 message: "Array index must be an integer".to_string(),
498 })?;
499 let borrowed = arr.borrow();
500 if index < 0 || index as usize >= borrowed.len() {
501 Ok(Value::none())
502 } else {
503 Ok(Value::some(borrowed[index as usize].clone()))
504 }
505 }
506
507 "first" => {
508 let borrowed = arr.borrow();
509 if borrowed.is_empty() {
510 Ok(Value::none())
511 } else {
512 Ok(Value::some(borrowed[0].clone()))
513 }
514 }
515
516 "last" => {
517 let borrowed = arr.borrow();
518 if borrowed.is_empty() {
519 Ok(Value::none())
520 } else {
521 Ok(Value::some(borrowed[borrowed.len() - 1].clone()))
522 }
523 }
524
525 "push" => {
526 if args.is_empty() {
527 return Err(LustError::RuntimeError {
528 message: "push requires a value argument".to_string(),
529 });
530 }
531
532 arr.borrow_mut().push(args[0].clone());
533 Ok(Value::Nil)
534 }
535
536 "pop" => {
537 let popped = arr.borrow_mut().pop();
538 match popped {
539 Some(val) => Ok(Value::some(val)),
540 None => Ok(Value::none()),
541 }
542 }
543
544 "map" => {
545 if args.is_empty() {
546 return Err(LustError::RuntimeError {
547 message: "map requires a function argument".to_string(),
548 });
549 }
550
551 let func = &args[0];
552 let borrowed = arr.borrow();
553 let mut result = Vec::new();
554 for elem in borrowed.iter() {
555 let mapped_value = self.call_value(func, vec![elem.clone()])?;
556 result.push(mapped_value);
557 }
558
559 Ok(Value::array(result))
560 }
561
562 "filter" => {
563 if args.is_empty() {
564 return Err(LustError::RuntimeError {
565 message: "filter requires a function argument".to_string(),
566 });
567 }
568
569 let func = &args[0];
570 let borrowed = arr.borrow();
571 let mut result = Vec::new();
572 for elem in borrowed.iter() {
573 let keep = self.call_value(func, vec![elem.clone()])?;
574 if keep.is_truthy() {
575 result.push(elem.clone());
576 }
577 }
578
579 Ok(Value::array(result))
580 }
581
582 "reduce" => {
583 if args.len() < 2 {
584 return Err(LustError::RuntimeError {
585 message: "reduce requires an initial value and function".to_string(),
586 });
587 }
588
589 let init_value = &args[0];
590 let func = &args[1];
591 let borrowed = arr.borrow();
592 let mut accumulator = init_value.clone();
593 for elem in borrowed.iter() {
594 accumulator = self.call_value(func, vec![accumulator, elem.clone()])?;
595 }
596
597 Ok(accumulator)
598 }
599
600 "slice" => {
601 if args.len() < 2 {
602 return Err(LustError::RuntimeError {
603 message: "slice requires start and end indices".to_string(),
604 });
605 }
606
607 let start = args[0].as_int().ok_or_else(|| LustError::RuntimeError {
608 message: "Start index must be an integer".to_string(),
609 })? as usize;
610 let end = args[1].as_int().ok_or_else(|| LustError::RuntimeError {
611 message: "End index must be an integer".to_string(),
612 })? as usize;
613 let borrowed = arr.borrow();
614 if start > borrowed.len() || end > borrowed.len() || start > end {
615 return Err(LustError::RuntimeError {
616 message: "Invalid slice indices".to_string(),
617 });
618 }
619
620 let sliced = borrowed[start..end].to_vec();
621 Ok(Value::array(sliced))
622 }
623
624 "clear" => {
625 arr.borrow_mut().clear();
626 Ok(Value::Nil)
627 }
628
629 "is_empty" => Ok(Value::Bool(arr.borrow().is_empty())),
630 _ => Err(LustError::RuntimeError {
631 message: format!("Array has no method '{}'", method_name),
632 }),
633 },
634 Value::String(s) => match method_name {
635 "iter" => {
636 let items: Vec<Value> =
637 s.chars().map(|c| Value::string(c.to_string())).collect();
638 let iter = crate::bytecode::value::IteratorState::Array { items, index: 0 };
639 Ok(Value::Iterator(Rc::new(RefCell::new(iter))))
640 }
641
642 "len" => Ok(Value::Int(int_from_usize(s.len()))),
643 "substring" => {
644 if args.len() < 2 {
645 return Err(LustError::RuntimeError {
646 message: "substring requires start and end indices".to_string(),
647 });
648 }
649
650 let start = args[0].as_int().ok_or_else(|| LustError::RuntimeError {
651 message: "Start index must be an integer".to_string(),
652 })? as usize;
653 let end = args[1].as_int().ok_or_else(|| LustError::RuntimeError {
654 message: "End index must be an integer".to_string(),
655 })? as usize;
656 if start > s.len() || end > s.len() || start > end {
657 return Err(LustError::RuntimeError {
658 message: "Invalid substring indices".to_string(),
659 });
660 }
661
662 Ok(Value::string(&s[start..end]))
663 }
664
665 "find" => {
666 if args.is_empty() {
667 return Err(LustError::RuntimeError {
668 message: "find requires a search string".to_string(),
669 });
670 }
671
672 let search = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
673 message: "Search string must be a string".to_string(),
674 })?;
675 match s.find(search) {
676 Some(pos) => Ok(Value::some(Value::Int(int_from_usize(pos)))),
677 None => Ok(Value::none()),
678 }
679 }
680
681 "starts_with" => {
682 if args.is_empty() {
683 return Err(LustError::RuntimeError {
684 message: "starts_with requires a prefix string".to_string(),
685 });
686 }
687
688 let prefix = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
689 message: "Prefix must be a string".to_string(),
690 })?;
691 Ok(Value::Bool(s.starts_with(prefix)))
692 }
693
694 "ends_with" => {
695 if args.is_empty() {
696 return Err(LustError::RuntimeError {
697 message: "ends_with requires a suffix string".to_string(),
698 });
699 }
700
701 let suffix = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
702 message: "Suffix must be a string".to_string(),
703 })?;
704 Ok(Value::Bool(s.ends_with(suffix)))
705 }
706
707 "split" => {
708 if args.is_empty() {
709 return Err(LustError::RuntimeError {
710 message: "split requires a separator string".to_string(),
711 });
712 }
713
714 let separator = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
715 message: "Separator must be a string".to_string(),
716 })?;
717 let parts: Vec<Value> =
718 s.split(separator).map(|part| Value::string(part)).collect();
719 Ok(Value::array(parts))
720 }
721
722 "trim" => Ok(Value::string(s.trim())),
723 "trim_start" => Ok(Value::string(s.trim_start())),
724 "trim_end" => Ok(Value::string(s.trim_end())),
725 "replace" => {
726 if args.len() < 2 {
727 return Err(LustError::RuntimeError {
728 message: "replace requires 'from' and 'to' string arguments"
729 .to_string(),
730 });
731 }
732
733 let from = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
734 message: "First argument must be a string".to_string(),
735 })?;
736 let to = args[1].as_string().ok_or_else(|| LustError::RuntimeError {
737 message: "Second argument must be a string".to_string(),
738 })?;
739 Ok(Value::string(&s.replace(from, to)))
740 }
741
742 "to_upper" => Ok(Value::string(&s.to_uppercase())),
743 "to_lower" => Ok(Value::string(&s.to_lowercase())),
744 "contains" => {
745 if args.is_empty() {
746 return Err(LustError::RuntimeError {
747 message: "contains requires a search string".to_string(),
748 });
749 }
750
751 let search = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
752 message: "Search string must be a string".to_string(),
753 })?;
754 Ok(Value::Bool(s.contains(search)))
755 }
756
757 "is_empty" => Ok(Value::Bool(s.is_empty())),
758 "chars" => {
759 let chars: Vec<Value> =
760 s.chars().map(|c| Value::string(&c.to_string())).collect();
761 Ok(Value::array(chars))
762 }
763
764 "lines" => {
765 let lines: Vec<Value> = s.lines().map(|line| Value::string(line)).collect();
766 Ok(Value::array(lines))
767 }
768
769 _ => Err(LustError::RuntimeError {
770 message: format!("String has no method '{}'", method_name),
771 }),
772 },
773 Value::Map(map) => {
774 use crate::bytecode::ValueKey;
775 match method_name {
776 "iter" => {
777 let items: Vec<(ValueKey, Value)> = map
778 .borrow()
779 .iter()
780 .map(|(k, v)| (k.clone(), v.clone()))
781 .collect();
782 let iter =
783 crate::bytecode::value::IteratorState::MapPairs { items, index: 0 };
784 return Ok(Value::Iterator(Rc::new(RefCell::new(iter))));
785 }
786
787 "len" => Ok(Value::Int(int_from_usize(map.borrow().len()))),
788 "get" => {
789 if args.is_empty() {
790 return Err(LustError::RuntimeError {
791 message: "get requires a key argument".to_string(),
792 });
793 }
794
795 let key = ValueKey::from_value(&args[0]).ok_or_else(|| {
796 LustError::RuntimeError {
797 message: format!(
798 "Cannot use {:?} as map key (not hashable)",
799 args[0]
800 ),
801 }
802 })?;
803 match map.borrow().get(&key) {
804 Some(value) => Ok(Value::some(value.clone())),
805 None => Ok(Value::none()),
806 }
807 }
808
809 "set" => {
810 if args.len() < 2 {
811 return Err(LustError::RuntimeError {
812 message: "set requires key and value arguments".to_string(),
813 });
814 }
815
816 let key = ValueKey::from_value(&args[0]).ok_or_else(|| {
817 LustError::RuntimeError {
818 message: format!(
819 "Cannot use {:?} as map key (not hashable)",
820 args[0]
821 ),
822 }
823 })?;
824 let value = args[1].clone();
825 map.borrow_mut().insert(key, value);
826 Ok(Value::Nil)
827 }
828
829 "has" => {
830 if args.is_empty() {
831 return Err(LustError::RuntimeError {
832 message: "has requires a key argument".to_string(),
833 });
834 }
835
836 let key = ValueKey::from_value(&args[0]).ok_or_else(|| {
837 LustError::RuntimeError {
838 message: format!(
839 "Cannot use {:?} as map key (not hashable)",
840 args[0]
841 ),
842 }
843 })?;
844 Ok(Value::Bool(map.borrow().contains_key(&key)))
845 }
846
847 "delete" => {
848 if args.is_empty() {
849 return Err(LustError::RuntimeError {
850 message: "delete requires a key argument".to_string(),
851 });
852 }
853
854 let key = ValueKey::from_value(&args[0]).ok_or_else(|| {
855 LustError::RuntimeError {
856 message: format!(
857 "Cannot use {:?} as map key (not hashable)",
858 args[0]
859 ),
860 }
861 })?;
862 match map.borrow_mut().remove(&key) {
863 Some(value) => Ok(Value::some(value)),
864 None => Ok(Value::none()),
865 }
866 }
867
868 "keys" => {
869 let keys: Vec<Value> = map.borrow().keys().map(|k| k.to_value()).collect();
870 Ok(Value::array(keys))
871 }
872
873 "values" => {
874 let values: Vec<Value> = map.borrow().values().cloned().collect();
875 Ok(Value::array(values))
876 }
877
878 _ => Err(LustError::RuntimeError {
879 message: format!("Map has no method '{}'", method_name),
880 }),
881 }
882 }
883
884 Value::Table(table) => {
885 use crate::bytecode::ValueKey;
886 match method_name {
887 "iter" => {
888 let items: Vec<(ValueKey, Value)> = table
889 .borrow()
890 .iter()
891 .map(|(k, v)| (k.clone(), v.clone()))
892 .collect();
893 let iter =
894 crate::bytecode::value::IteratorState::TablePairs { items, index: 0 };
895 return Ok(Value::Iterator(Rc::new(RefCell::new(iter))));
896 }
897
898 "len" => Ok(Value::Int(int_from_usize(table.borrow().len()))),
899 "get" => {
900 if args.is_empty() {
901 return Err(LustError::RuntimeError {
902 message: "get requires a key argument".to_string(),
903 });
904 }
905
906 let key = ValueKey::from_value(&args[0]).ok_or_else(|| {
907 LustError::RuntimeError {
908 message: format!(
909 "Cannot use {:?} as table key (not hashable)",
910 args[0]
911 ),
912 }
913 })?;
914 match table.borrow().get(&key) {
915 Some(value) => Ok(Value::some(value.clone())),
916 None => Ok(Value::none()),
917 }
918 }
919
920 "set" => {
921 if args.len() < 2 {
922 return Err(LustError::RuntimeError {
923 message: "set requires key and value arguments".to_string(),
924 });
925 }
926
927 let key = ValueKey::from_value(&args[0]).ok_or_else(|| {
928 LustError::RuntimeError {
929 message: format!(
930 "Cannot use {:?} as table key (not hashable)",
931 args[0]
932 ),
933 }
934 })?;
935 let value = args[1].clone();
936 table.borrow_mut().insert(key, value);
937 Ok(Value::Nil)
938 }
939
940 "has" => {
941 if args.is_empty() {
942 return Err(LustError::RuntimeError {
943 message: "has requires a key argument".to_string(),
944 });
945 }
946
947 let key = ValueKey::from_value(&args[0]).ok_or_else(|| {
948 LustError::RuntimeError {
949 message: format!(
950 "Cannot use {:?} as table key (not hashable)",
951 args[0]
952 ),
953 }
954 })?;
955 Ok(Value::Bool(table.borrow().contains_key(&key)))
956 }
957
958 "delete" => {
959 if args.is_empty() {
960 return Err(LustError::RuntimeError {
961 message: "delete requires a key argument".to_string(),
962 });
963 }
964
965 let key = ValueKey::from_value(&args[0]).ok_or_else(|| {
966 LustError::RuntimeError {
967 message: format!(
968 "Cannot use {:?} as table key (not hashable)",
969 args[0]
970 ),
971 }
972 })?;
973 match table.borrow_mut().remove(&key) {
974 Some(value) => Ok(Value::some(value)),
975 None => Ok(Value::none()),
976 }
977 }
978
979 "keys" => {
980 let keys: Vec<Value> =
981 table.borrow().keys().map(|k| k.to_value()).collect();
982 Ok(Value::array(keys))
983 }
984
985 "values" => {
986 let values: Vec<Value> = table.borrow().values().cloned().collect();
987 Ok(Value::array(values))
988 }
989
990 _ => Err(LustError::RuntimeError {
991 message: format!("Table has no method '{}'", method_name),
992 }),
993 }
994 }
995
996 Value::Iterator(state_rc) => match method_name {
997 "iter" => Ok(Value::Iterator(state_rc.clone())),
998 "next" => {
999 use crate::bytecode::value::IteratorState;
1000 let mut state = state_rc.borrow_mut();
1001 match &mut *state {
1002 IteratorState::Array { items, index } => {
1003 if *index < items.len() {
1004 let v = items[*index].clone();
1005 *index += 1;
1006 Ok(Value::some(v))
1007 } else {
1008 Ok(Value::none())
1009 }
1010 }
1011
1012 IteratorState::MapPairs { items, index } => {
1013 if *index < items.len() {
1014 let (k, v) = items[*index].clone();
1015 *index += 1;
1016 Ok(Value::some(Value::array(vec![k.to_value(), v])))
1017 } else {
1018 Ok(Value::none())
1019 }
1020 }
1021
1022 IteratorState::TablePairs { items, index } => {
1023 if *index < items.len() {
1024 let (k, v) = items[*index].clone();
1025 *index += 1;
1026 Ok(Value::some(Value::array(vec![k.to_value(), v])))
1027 } else {
1028 Ok(Value::none())
1029 }
1030 }
1031 }
1032 }
1033
1034 _ => Err(LustError::RuntimeError {
1035 message: format!("Iterator has no method '{}'", method_name),
1036 }),
1037 },
1038 Value::Float(f) => match method_name {
1039 "to_int" => {
1040 if !args.is_empty() {
1041 return Err(LustError::RuntimeError {
1042 message: "to_int() takes no arguments".to_string(),
1043 });
1044 }
1045
1046 Ok(Value::Int(int_from_float(*f)))
1047 }
1048
1049 "floor" => {
1050 if !args.is_empty() {
1051 return Err(LustError::RuntimeError {
1052 message: "floor() takes no arguments".to_string(),
1053 });
1054 }
1055
1056 Ok(Value::Float(float_floor(*f)))
1057 }
1058
1059 "ceil" => {
1060 if !args.is_empty() {
1061 return Err(LustError::RuntimeError {
1062 message: "ceil() takes no arguments".to_string(),
1063 });
1064 }
1065
1066 Ok(Value::Float(float_ceil(*f)))
1067 }
1068
1069 "round" => {
1070 if !args.is_empty() {
1071 return Err(LustError::RuntimeError {
1072 message: "round() takes no arguments".to_string(),
1073 });
1074 }
1075
1076 Ok(Value::Float(float_round(*f)))
1077 }
1078
1079 "sqrt" => {
1080 if !args.is_empty() {
1081 return Err(LustError::RuntimeError {
1082 message: "sqrt() takes no arguments".to_string(),
1083 });
1084 }
1085
1086 if *f < 0.0 {
1087 return Err(LustError::RuntimeError {
1088 message: "sqrt() requires a non-negative number".to_string(),
1089 });
1090 }
1091
1092 Ok(Value::Float(float_sqrt(*f)))
1093 }
1094
1095 "abs" => {
1096 if !args.is_empty() {
1097 return Err(LustError::RuntimeError {
1098 message: "abs() takes no arguments".to_string(),
1099 });
1100 }
1101
1102 Ok(Value::Float(float_abs(*f)))
1103 }
1104
1105 "clamp" => {
1106 if args.len() != 2 {
1107 return Err(LustError::RuntimeError {
1108 message: "clamp() requires 2 arguments (min, max)".to_string(),
1109 });
1110 }
1111
1112 let min = args[0].as_float().ok_or_else(|| LustError::RuntimeError {
1113 message: "clamp() min must be a number".to_string(),
1114 })?;
1115 let max = args[1].as_float().ok_or_else(|| LustError::RuntimeError {
1116 message: "clamp() max must be a number".to_string(),
1117 })?;
1118 if min > max {
1119 return Err(LustError::RuntimeError {
1120 message: "clamp() min must be less than or equal to max".to_string(),
1121 });
1122 }
1123
1124 Ok(Value::Float(float_clamp(*f, min, max)))
1125 }
1126
1127 _ => Err(LustError::RuntimeError {
1128 message: format!("Float has no method '{}'", method_name),
1129 }),
1130 },
1131 Value::Int(i) => match method_name {
1132 "to_float" => {
1133 if !args.is_empty() {
1134 return Err(LustError::RuntimeError {
1135 message: "to_float() takes no arguments".to_string(),
1136 });
1137 }
1138
1139 Ok(Value::Float(float_from_int(*i)))
1140 }
1141
1142 "abs" => {
1143 if !args.is_empty() {
1144 return Err(LustError::RuntimeError {
1145 message: "abs() takes no arguments".to_string(),
1146 });
1147 }
1148
1149 Ok(Value::Int(i.abs()))
1150 }
1151
1152 "clamp" => {
1153 if args.len() != 2 {
1154 return Err(LustError::RuntimeError {
1155 message: "clamp() requires 2 arguments (min, max)".to_string(),
1156 });
1157 }
1158
1159 let min = args[0].as_int().ok_or_else(|| LustError::RuntimeError {
1160 message: "clamp() min must be an integer".to_string(),
1161 })?;
1162 let max = args[1].as_int().ok_or_else(|| LustError::RuntimeError {
1163 message: "clamp() max must be an integer".to_string(),
1164 })?;
1165 if min > max {
1166 return Err(LustError::RuntimeError {
1167 message: "clamp() min must be less than or equal to max".to_string(),
1168 });
1169 }
1170
1171 Ok(Value::Int((*i).clamp(min, max)))
1172 }
1173
1174 _ => Err(LustError::RuntimeError {
1175 message: format!("Int has no method '{}'", method_name),
1176 }),
1177 },
1178 _ => Err(LustError::RuntimeError {
1179 message: format!(
1180 "Type {:?} has no method '{}'",
1181 object.type_of(),
1182 method_name
1183 ),
1184 }),
1185 }
1186 }
1187}