lust/vm/
tasks.rs

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