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