lust/vm/
tasks.rs

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