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 match object {
321 Value::Enum {
322 enum_name,
323 variant,
324 values,
325 } if enum_name == "Option" => match method_name {
326 "is_some" => Ok(Value::Bool(variant == "Some")),
327 "is_none" => Ok(Value::Bool(variant == "None")),
328 "unwrap" => {
329 if variant == "Some" {
330 if let Some(vals) = values {
331 if !vals.is_empty() {
332 Ok(vals[0].clone())
333 } else {
334 Err(LustError::RuntimeError {
335 message: "Option::Some has no value".to_string(),
336 })
337 }
338 } else {
339 Err(LustError::RuntimeError {
340 message: "Option::Some has no value".to_string(),
341 })
342 }
343 } else {
344 Err(LustError::RuntimeError {
345 message: "Called unwrap() on Option::None".to_string(),
346 })
347 }
348 }
349
350 "unwrap_or" => {
351 if args.is_empty() {
352 return Err(LustError::RuntimeError {
353 message: "unwrap_or requires a default value".to_string(),
354 });
355 }
356
357 if variant == "Some" {
358 if let Some(vals) = values {
359 if !vals.is_empty() {
360 Ok(vals[0].clone())
361 } else {
362 Ok(args[0].clone())
363 }
364 } else {
365 Ok(args[0].clone())
366 }
367 } else {
368 Ok(args[0].clone())
369 }
370 }
371
372 _ => Err(LustError::RuntimeError {
373 message: format!("Option has no method '{}'", method_name),
374 }),
375 },
376 Value::Enum {
377 enum_name,
378 variant,
379 values,
380 } if enum_name == "Result" => match method_name {
381 "is_ok" => Ok(Value::Bool(variant == "Ok")),
382 "is_err" => Ok(Value::Bool(variant == "Err")),
383 "unwrap" => {
384 if variant == "Ok" {
385 if let Some(vals) = values {
386 if !vals.is_empty() {
387 Ok(vals[0].clone())
388 } else {
389 Err(LustError::RuntimeError {
390 message: "Result::Ok has no value".to_string(),
391 })
392 }
393 } else {
394 Err(LustError::RuntimeError {
395 message: "Result::Ok has no value".to_string(),
396 })
397 }
398 } else {
399 Err(LustError::RuntimeError {
400 message: "Called unwrap() on Result::Err".to_string(),
401 })
402 }
403 }
404
405 "unwrap_or" => {
406 if args.is_empty() {
407 return Err(LustError::RuntimeError {
408 message: "unwrap_or requires a default value".to_string(),
409 });
410 }
411
412 if variant == "Ok" {
413 if let Some(vals) = values {
414 if !vals.is_empty() {
415 Ok(vals[0].clone())
416 } else {
417 Ok(args[0].clone())
418 }
419 } else {
420 Ok(args[0].clone())
421 }
422 } else {
423 Ok(args[0].clone())
424 }
425 }
426
427 _ => Err(LustError::RuntimeError {
428 message: format!("Result has no method '{}'", method_name),
429 }),
430 },
431 Value::Array(arr) => match method_name {
432 "iter" => {
433 let items = arr.borrow().clone();
434 let iter = crate::bytecode::value::IteratorState::Array { items, index: 0 };
435 Ok(Value::Iterator(Rc::new(RefCell::new(iter))))
436 }
437
438 "len" => Ok(Value::Int(int_from_usize(arr.borrow().len()))),
439 "get" => {
440 if args.is_empty() {
441 return Err(LustError::RuntimeError {
442 message: "get requires an index argument".to_string(),
443 });
444 }
445
446 let index = args[0].as_int().ok_or_else(|| LustError::RuntimeError {
447 message: "Array index must be an integer".to_string(),
448 })?;
449 let borrowed = arr.borrow();
450 if index < 0 || index as usize >= borrowed.len() {
451 Ok(Value::none())
452 } else {
453 Ok(Value::some(borrowed[index as usize].clone()))
454 }
455 }
456
457 "first" => {
458 let borrowed = arr.borrow();
459 if borrowed.is_empty() {
460 Ok(Value::none())
461 } else {
462 Ok(Value::some(borrowed[0].clone()))
463 }
464 }
465
466 "last" => {
467 let borrowed = arr.borrow();
468 if borrowed.is_empty() {
469 Ok(Value::none())
470 } else {
471 Ok(Value::some(borrowed[borrowed.len() - 1].clone()))
472 }
473 }
474
475 "push" => {
476 if args.is_empty() {
477 return Err(LustError::RuntimeError {
478 message: "push requires a value argument".to_string(),
479 });
480 }
481
482 arr.borrow_mut().push(args[0].clone());
483 Ok(Value::Nil)
484 }
485
486 "pop" => {
487 let popped = arr.borrow_mut().pop();
488 match popped {
489 Some(val) => Ok(Value::some(val)),
490 None => Ok(Value::none()),
491 }
492 }
493
494 "map" => {
495 if args.is_empty() {
496 return Err(LustError::RuntimeError {
497 message: "map requires a function argument".to_string(),
498 });
499 }
500
501 let func = &args[0];
502 let borrowed = arr.borrow();
503 let mut result = Vec::new();
504 for elem in borrowed.iter() {
505 let mapped_value = self.call_value(func, vec![elem.clone()])?;
506 result.push(mapped_value);
507 }
508
509 Ok(Value::array(result))
510 }
511
512 "filter" => {
513 if args.is_empty() {
514 return Err(LustError::RuntimeError {
515 message: "filter requires a function argument".to_string(),
516 });
517 }
518
519 let func = &args[0];
520 let borrowed = arr.borrow();
521 let mut result = Vec::new();
522 for elem in borrowed.iter() {
523 let keep = self.call_value(func, vec![elem.clone()])?;
524 if keep.is_truthy() {
525 result.push(elem.clone());
526 }
527 }
528
529 Ok(Value::array(result))
530 }
531
532 "reduce" => {
533 if args.len() < 2 {
534 return Err(LustError::RuntimeError {
535 message: "reduce requires an initial value and function".to_string(),
536 });
537 }
538
539 let init_value = &args[0];
540 let func = &args[1];
541 let borrowed = arr.borrow();
542 let mut accumulator = init_value.clone();
543 for elem in borrowed.iter() {
544 accumulator = self.call_value(func, vec![accumulator, elem.clone()])?;
545 }
546
547 Ok(accumulator)
548 }
549
550 "slice" => {
551 if args.len() < 2 {
552 return Err(LustError::RuntimeError {
553 message: "slice requires start and end indices".to_string(),
554 });
555 }
556
557 let start = args[0].as_int().ok_or_else(|| LustError::RuntimeError {
558 message: "Start index must be an integer".to_string(),
559 })? as usize;
560 let end = args[1].as_int().ok_or_else(|| LustError::RuntimeError {
561 message: "End index must be an integer".to_string(),
562 })? as usize;
563 let borrowed = arr.borrow();
564 if start > borrowed.len() || end > borrowed.len() || start > end {
565 return Err(LustError::RuntimeError {
566 message: "Invalid slice indices".to_string(),
567 });
568 }
569
570 let sliced = borrowed[start..end].to_vec();
571 Ok(Value::array(sliced))
572 }
573
574 "clear" => {
575 arr.borrow_mut().clear();
576 Ok(Value::Nil)
577 }
578
579 "is_empty" => Ok(Value::Bool(arr.borrow().is_empty())),
580 _ => Err(LustError::RuntimeError {
581 message: format!("Array has no method '{}'", method_name),
582 }),
583 },
584 Value::String(s) => match method_name {
585 "iter" => {
586 let items: Vec<Value> =
587 s.chars().map(|c| Value::string(c.to_string())).collect();
588 let iter = crate::bytecode::value::IteratorState::Array { items, index: 0 };
589 Ok(Value::Iterator(Rc::new(RefCell::new(iter))))
590 }
591
592 "len" => Ok(Value::Int(int_from_usize(s.len()))),
593 "substring" => {
594 if args.len() < 2 {
595 return Err(LustError::RuntimeError {
596 message: "substring requires start and end indices".to_string(),
597 });
598 }
599
600 let start = args[0].as_int().ok_or_else(|| LustError::RuntimeError {
601 message: "Start index must be an integer".to_string(),
602 })? as usize;
603 let end = args[1].as_int().ok_or_else(|| LustError::RuntimeError {
604 message: "End index must be an integer".to_string(),
605 })? as usize;
606 if start > s.len() || end > s.len() || start > end {
607 return Err(LustError::RuntimeError {
608 message: "Invalid substring indices".to_string(),
609 });
610 }
611
612 Ok(Value::string(&s[start..end]))
613 }
614
615 "find" => {
616 if args.is_empty() {
617 return Err(LustError::RuntimeError {
618 message: "find requires a search string".to_string(),
619 });
620 }
621
622 let search = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
623 message: "Search string must be a string".to_string(),
624 })?;
625 match s.find(search) {
626 Some(pos) => Ok(Value::some(Value::Int(int_from_usize(pos)))),
627 None => Ok(Value::none()),
628 }
629 }
630
631 "starts_with" => {
632 if args.is_empty() {
633 return Err(LustError::RuntimeError {
634 message: "starts_with requires a prefix string".to_string(),
635 });
636 }
637
638 let prefix = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
639 message: "Prefix must be a string".to_string(),
640 })?;
641 Ok(Value::Bool(s.starts_with(prefix)))
642 }
643
644 "ends_with" => {
645 if args.is_empty() {
646 return Err(LustError::RuntimeError {
647 message: "ends_with requires a suffix string".to_string(),
648 });
649 }
650
651 let suffix = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
652 message: "Suffix must be a string".to_string(),
653 })?;
654 Ok(Value::Bool(s.ends_with(suffix)))
655 }
656
657 "split" => {
658 if args.is_empty() {
659 return Err(LustError::RuntimeError {
660 message: "split requires a separator string".to_string(),
661 });
662 }
663
664 let separator = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
665 message: "Separator must be a string".to_string(),
666 })?;
667 let parts: Vec<Value> =
668 s.split(separator).map(|part| Value::string(part)).collect();
669 Ok(Value::array(parts))
670 }
671
672 "trim" => Ok(Value::string(s.trim())),
673 "trim_start" => Ok(Value::string(s.trim_start())),
674 "trim_end" => Ok(Value::string(s.trim_end())),
675 "replace" => {
676 if args.len() < 2 {
677 return Err(LustError::RuntimeError {
678 message: "replace requires 'from' and 'to' string arguments"
679 .to_string(),
680 });
681 }
682
683 let from = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
684 message: "First argument must be a string".to_string(),
685 })?;
686 let to = args[1].as_string().ok_or_else(|| LustError::RuntimeError {
687 message: "Second argument must be a string".to_string(),
688 })?;
689 Ok(Value::string(&s.replace(from, to)))
690 }
691
692 "to_upper" => Ok(Value::string(&s.to_uppercase())),
693 "to_lower" => Ok(Value::string(&s.to_lowercase())),
694 "contains" => {
695 if args.is_empty() {
696 return Err(LustError::RuntimeError {
697 message: "contains requires a search string".to_string(),
698 });
699 }
700
701 let search = args[0].as_string().ok_or_else(|| LustError::RuntimeError {
702 message: "Search string must be a string".to_string(),
703 })?;
704 Ok(Value::Bool(s.contains(search)))
705 }
706
707 "is_empty" => Ok(Value::Bool(s.is_empty())),
708 "chars" => {
709 let chars: Vec<Value> =
710 s.chars().map(|c| Value::string(&c.to_string())).collect();
711 Ok(Value::array(chars))
712 }
713
714 "lines" => {
715 let lines: Vec<Value> = s.lines().map(|line| Value::string(line)).collect();
716 Ok(Value::array(lines))
717 }
718
719 _ => Err(LustError::RuntimeError {
720 message: format!("String has no method '{}'", method_name),
721 }),
722 },
723 Value::Map(map) => {
724 use crate::bytecode::ValueKey;
725 match method_name {
726 "iter" => {
727 let items: Vec<(ValueKey, Value)> = map
728 .borrow()
729 .iter()
730 .map(|(k, v)| (k.clone(), v.clone()))
731 .collect();
732 let iter =
733 crate::bytecode::value::IteratorState::MapPairs { items, index: 0 };
734 return Ok(Value::Iterator(Rc::new(RefCell::new(iter))));
735 }
736
737 "len" => Ok(Value::Int(int_from_usize(map.borrow().len()))),
738 "get" => {
739 if args.is_empty() {
740 return Err(LustError::RuntimeError {
741 message: "get requires a key argument".to_string(),
742 });
743 }
744
745 let key = ValueKey::from_value(&args[0]).ok_or_else(|| {
746 LustError::RuntimeError {
747 message: format!(
748 "Cannot use {:?} as map key (not hashable)",
749 args[0]
750 ),
751 }
752 })?;
753 match map.borrow().get(&key) {
754 Some(value) => Ok(Value::some(value.clone())),
755 None => Ok(Value::none()),
756 }
757 }
758
759 "set" => {
760 if args.len() < 2 {
761 return Err(LustError::RuntimeError {
762 message: "set requires key and value arguments".to_string(),
763 });
764 }
765
766 let key = ValueKey::from_value(&args[0]).ok_or_else(|| {
767 LustError::RuntimeError {
768 message: format!(
769 "Cannot use {:?} as map key (not hashable)",
770 args[0]
771 ),
772 }
773 })?;
774 let value = args[1].clone();
775 map.borrow_mut().insert(key, value);
776 Ok(Value::Nil)
777 }
778
779 "has" => {
780 if args.is_empty() {
781 return Err(LustError::RuntimeError {
782 message: "has requires a key argument".to_string(),
783 });
784 }
785
786 let key = ValueKey::from_value(&args[0]).ok_or_else(|| {
787 LustError::RuntimeError {
788 message: format!(
789 "Cannot use {:?} as map key (not hashable)",
790 args[0]
791 ),
792 }
793 })?;
794 Ok(Value::Bool(map.borrow().contains_key(&key)))
795 }
796
797 "delete" => {
798 if args.is_empty() {
799 return Err(LustError::RuntimeError {
800 message: "delete requires a key argument".to_string(),
801 });
802 }
803
804 let key = ValueKey::from_value(&args[0]).ok_or_else(|| {
805 LustError::RuntimeError {
806 message: format!(
807 "Cannot use {:?} as map key (not hashable)",
808 args[0]
809 ),
810 }
811 })?;
812 match map.borrow_mut().remove(&key) {
813 Some(value) => Ok(Value::some(value)),
814 None => Ok(Value::none()),
815 }
816 }
817
818 "keys" => {
819 let keys: Vec<Value> = map.borrow().keys().map(|k| k.to_value()).collect();
820 Ok(Value::array(keys))
821 }
822
823 "values" => {
824 let values: Vec<Value> = map.borrow().values().cloned().collect();
825 Ok(Value::array(values))
826 }
827
828 _ => Err(LustError::RuntimeError {
829 message: format!("Map has no method '{}'", method_name),
830 }),
831 }
832 }
833
834 Value::Iterator(state_rc) => match method_name {
835 "iter" => Ok(Value::Iterator(state_rc.clone())),
836 "next" => {
837 use crate::bytecode::value::IteratorState;
838 let mut state = state_rc.borrow_mut();
839 match &mut *state {
840 IteratorState::Array { items, index } => {
841 if *index < items.len() {
842 let v = items[*index].clone();
843 *index += 1;
844 Ok(Value::some(v))
845 } else {
846 Ok(Value::none())
847 }
848 }
849
850 IteratorState::MapPairs { items, index } => {
851 if *index < items.len() {
852 let (k, v) = items[*index].clone();
853 *index += 1;
854 Ok(Value::some(Value::array(vec![k.to_value(), v])))
855 } else {
856 Ok(Value::none())
857 }
858 }
859 }
860 }
861
862 _ => Err(LustError::RuntimeError {
863 message: format!("Iterator has no method '{}'", method_name),
864 }),
865 },
866 Value::Float(f) => match method_name {
867 "to_int" => {
868 if !args.is_empty() {
869 return Err(LustError::RuntimeError {
870 message: "to_int() takes no arguments".to_string(),
871 });
872 }
873
874 Ok(Value::Int(int_from_float(*f)))
875 }
876
877 "floor" => {
878 if !args.is_empty() {
879 return Err(LustError::RuntimeError {
880 message: "floor() takes no arguments".to_string(),
881 });
882 }
883
884 Ok(Value::Float(float_floor(*f)))
885 }
886
887 "ceil" => {
888 if !args.is_empty() {
889 return Err(LustError::RuntimeError {
890 message: "ceil() takes no arguments".to_string(),
891 });
892 }
893
894 Ok(Value::Float(float_ceil(*f)))
895 }
896
897 "round" => {
898 if !args.is_empty() {
899 return Err(LustError::RuntimeError {
900 message: "round() takes no arguments".to_string(),
901 });
902 }
903
904 Ok(Value::Float(float_round(*f)))
905 }
906
907 "sqrt" => {
908 if !args.is_empty() {
909 return Err(LustError::RuntimeError {
910 message: "sqrt() takes no arguments".to_string(),
911 });
912 }
913
914 if *f < 0.0 {
915 return Err(LustError::RuntimeError {
916 message: "sqrt() requires a non-negative number".to_string(),
917 });
918 }
919
920 Ok(Value::Float(float_sqrt(*f)))
921 }
922
923 "abs" => {
924 if !args.is_empty() {
925 return Err(LustError::RuntimeError {
926 message: "abs() takes no arguments".to_string(),
927 });
928 }
929
930 Ok(Value::Float(float_abs(*f)))
931 }
932
933 "clamp" => {
934 if args.len() != 2 {
935 return Err(LustError::RuntimeError {
936 message: "clamp() requires 2 arguments (min, max)".to_string(),
937 });
938 }
939
940 let min = args[0].as_float().ok_or_else(|| LustError::RuntimeError {
941 message: "clamp() min must be a number".to_string(),
942 })?;
943 let max = args[1].as_float().ok_or_else(|| LustError::RuntimeError {
944 message: "clamp() max must be a number".to_string(),
945 })?;
946 if min > max {
947 return Err(LustError::RuntimeError {
948 message: "clamp() min must be less than or equal to max".to_string(),
949 });
950 }
951
952 Ok(Value::Float(float_clamp(*f, min, max)))
953 }
954
955 _ => Err(LustError::RuntimeError {
956 message: format!("Float has no method '{}'", method_name),
957 }),
958 },
959 Value::Int(i) => match method_name {
960 "to_float" => {
961 if !args.is_empty() {
962 return Err(LustError::RuntimeError {
963 message: "to_float() takes no arguments".to_string(),
964 });
965 }
966
967 Ok(Value::Float(float_from_int(*i)))
968 }
969
970 "abs" => {
971 if !args.is_empty() {
972 return Err(LustError::RuntimeError {
973 message: "abs() takes no arguments".to_string(),
974 });
975 }
976
977 Ok(Value::Int(i.abs()))
978 }
979
980 "clamp" => {
981 if args.len() != 2 {
982 return Err(LustError::RuntimeError {
983 message: "clamp() requires 2 arguments (min, max)".to_string(),
984 });
985 }
986
987 let min = args[0].as_int().ok_or_else(|| LustError::RuntimeError {
988 message: "clamp() min must be an integer".to_string(),
989 })?;
990 let max = args[1].as_int().ok_or_else(|| LustError::RuntimeError {
991 message: "clamp() max must be an integer".to_string(),
992 })?;
993 if min > max {
994 return Err(LustError::RuntimeError {
995 message: "clamp() min must be less than or equal to max".to_string(),
996 });
997 }
998
999 Ok(Value::Int((*i).clamp(min, max)))
1000 }
1001
1002 _ => Err(LustError::RuntimeError {
1003 message: format!("Int has no method '{}'", method_name),
1004 }),
1005 },
1006 _ => Err(LustError::RuntimeError {
1007 message: format!(
1008 "Type {:?} has no method '{}'",
1009 object.type_of(),
1010 method_name
1011 ),
1012 }),
1013 }
1014 }
1015}