lust/vm/
tasks.rs

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