Skip to main content

zuzu_rust/
runtime.rs

1use regex::{Regex, RegexBuilder};
2use std::cell::{Cell, RefCell};
3use std::collections::{HashMap, HashSet};
4use std::ffi::c_void;
5use std::fmt;
6use std::fs;
7use std::future::Future;
8use std::io::{self, Write};
9use std::net::{TcpListener, TcpStream, UdpSocket};
10use std::ops::Deref;
11#[cfg(unix)]
12use std::os::unix::net::{UnixListener, UnixStream};
13use std::path::{Path, PathBuf};
14use std::rc::{Rc, Weak};
15use std::sync::mpsc;
16use std::sync::{
17    atomic::{AtomicBool, Ordering},
18    Arc,
19};
20use std::time::{Duration, Instant};
21
22mod collection;
23mod executor;
24mod stdlib;
25
26use self::collection::common::{
27    collection_contains, collection_difference, collection_intersection, collection_subset,
28    collection_union, construct_pair, construct_pairlist, expect_pair_like,
29    is_mutating_collection_method, pairlist_eq, reject_named_args, require_arity,
30};
31use self::executor::AsyncExecutor;
32use crate::ast::{
33    BlockStatement, CallArgument, ClassDeclaration, ClassMember, DeclarationBindingEntry, DictKey,
34    Expression, FieldDeclaration, ForStatement, FunctionDeclaration, ImportDeclaration,
35    MethodDeclaration, Parameter, Program, Statement, SwitchStatement, TemplatePart,
36    TraitDeclaration, TryStatement, VariableUnpackDeclaration,
37};
38use crate::sema;
39use crate::{
40    parse_program_with_compile_options, parse_program_with_compile_options_and_source_file,
41    OptimizationOptions, OptimizationPass, ParseOptions, Result, ZuzuRustError,
42};
43
44#[derive(Clone, Default)]
45pub struct ExecutionOutput {
46    pub stdout: String,
47    pub stderr: String,
48}
49
50#[derive(Debug, Clone, PartialEq)]
51pub enum HostValue {
52    Null,
53    Bool(bool),
54    Number(f64),
55    String(String),
56    Binary(Vec<u8>),
57    Array(Vec<HostValue>),
58    Dict(HashMap<String, HostValue>),
59    PairList(Vec<(String, HostValue)>),
60    Path(PathBuf),
61}
62
63#[derive(Clone)]
64pub struct Runtime {
65    inner: Rc<RuntimeInner>,
66}
67
68pub struct RuntimeInner {
69    module_roots: Vec<PathBuf>,
70    policy: RuntimePolicy,
71    run_sema: bool,
72    infer_types: bool,
73    optimizations: OptimizationOptions,
74    module_cache: RefCell<HashMap<String, ModuleRecord>>,
75    regex_cache: RefCell<HashMap<(String, String), Regex>>,
76    per_object_trait_class_cache: RefCell<HashMap<String, Rc<UserClassValue>>>,
77    module_loading: RefCell<HashSet<String>>,
78    output: RefCell<ExecutionOutput>,
79    special_props: RefCell<Vec<HashMap<String, Value>>>,
80    thrown_values: RefCell<HashMap<String, Value>>,
81    next_thrown_id: RefCell<usize>,
82    path_line_cursors: RefCell<HashMap<String, usize>>,
83    socket_state: RefCell<SocketState>,
84    current_env_stack: RefCell<Vec<Rc<Environment>>>,
85    current_method_stack: RefCell<Vec<Rc<MethodValue>>>,
86    signal_handlers: RefCell<HashMap<String, Vec<Value>>>,
87    db_state: RefCell<self::stdlib::DbState>,
88    clib_state: RefCell<self::stdlib::ClibState>,
89    running_async_functions: RefCell<Vec<usize>>,
90    polling_tasks: RefCell<Vec<usize>>,
91    background_tasks: RefCell<Vec<Rc<RefCell<TaskState>>>>,
92    worker_endpoints: RefCell<HashMap<usize, WorkerEndpointState>>,
93    next_worker_endpoint_id: RefCell<usize>,
94    worker_cancel_requested: Option<Arc<AtomicBool>>,
95    async_executor: AsyncExecutor,
96}
97
98impl Deref for Runtime {
99    type Target = RuntimeInner;
100
101    fn deref(&self) -> &Self::Target {
102        &self.inner
103    }
104}
105
106pub struct ReplEvalResult {
107    pub output: ExecutionOutput,
108    pub value: String,
109}
110
111pub struct ReplSession<'runtime> {
112    runtime: &'runtime Runtime,
113    env: Rc<Environment>,
114}
115
116pub struct LoadedScript {
117    _runtime: Runtime,
118    env: Rc<Environment>,
119}
120
121impl LoadedScript {
122    pub fn has_function(&self, name: &str) -> bool {
123        matches!(
124            self.env.get_optional(name),
125            Some(Value::Function(_)) | Some(Value::NativeFunction(_))
126        )
127    }
128
129    pub fn call(&self, name: &str, args: Vec<HostValue>) -> Result<HostValue> {
130        self._runtime
131            .async_executor
132            .enter(|| self.call_inner(name, args))
133    }
134
135    pub fn call_request(&self, env: HostValue) -> Result<HostValue> {
136        self.call("__request__", vec![env])
137    }
138
139    fn call_inner(&self, name: &str, args: Vec<HostValue>) -> Result<HostValue> {
140        let callee = self.env.get(name)?;
141        let args = args
142            .into_iter()
143            .map(|value| self._runtime.host_value_to_value(value))
144            .collect::<Result<Vec<_>>>()?;
145        let result = self._runtime.call_value(callee, args, Vec::new())?;
146        let result = self._runtime.await_if_task(result)?;
147        self._runtime.value_to_host_value(result)
148    }
149}
150
151#[derive(Clone, Default)]
152pub struct RuntimePolicy {
153    denied_capabilities: HashSet<String>,
154    denied_modules: HashSet<String>,
155    debug_level: u32,
156}
157
158impl RuntimePolicy {
159    pub fn new() -> Self {
160        Self::default()
161    }
162
163    pub fn deny_capability(mut self, capability: impl Into<String>) -> Self {
164        let capability = capability.into();
165        if !capability.is_empty() {
166            self.denied_capabilities.insert(capability);
167        }
168        self
169    }
170
171    pub fn deny_module(mut self, module: impl Into<String>) -> Self {
172        let module = module.into();
173        if !module.is_empty() {
174            self.denied_modules.insert(module);
175        }
176        self
177    }
178
179    pub fn debug_level(mut self, level: u32) -> Self {
180        self.debug_level = level;
181        self
182    }
183}
184
185pub(in crate::runtime) const DENIAL_CAPABILITIES: &[&str] = &[
186    "fs", "net", "perl", "js", "proc", "db", "clib", "gui", "worker",
187];
188
189fn quote_zuzu_string(text: &str) -> String {
190    let mut out = String::from("\"");
191    for ch in text.chars() {
192        match ch {
193            '\\' => out.push_str("\\\\"),
194            '"' => out.push_str("\\\""),
195            '\n' => out.push_str("\\n"),
196            '\r' => out.push_str("\\r"),
197            '\t' => out.push_str("\\t"),
198            other => out.push(other),
199        }
200    }
201    out.push('"');
202    out
203}
204
205#[derive(Clone)]
206struct ModuleRecord {
207    exports: HashMap<String, Value>,
208}
209
210#[derive(Default)]
211struct SocketState {
212    next_socket_id: usize,
213    tcp_servers: HashMap<String, TcpListener>,
214    tcp_sockets: HashMap<String, TcpSocketState>,
215    udp_sockets: HashMap<String, UdpSocket>,
216    #[cfg(unix)]
217    unix_servers: HashMap<String, UnixServerState>,
218    #[cfg(unix)]
219    unix_sockets: HashMap<String, UnixSocketState>,
220}
221
222struct TcpSocketState {
223    stream: TcpStream,
224    read_buffer: Vec<u8>,
225}
226
227#[cfg(unix)]
228struct UnixServerState {
229    listener: UnixListener,
230    path: PathBuf,
231}
232
233#[cfg(unix)]
234struct UnixSocketState {
235    stream: UnixStream,
236    read_buffer: Vec<u8>,
237}
238
239#[cfg(unix)]
240impl Drop for UnixServerState {
241    fn drop(&mut self) {
242        let _ = fs::remove_file(&self.path);
243    }
244}
245
246#[derive(Clone)]
247enum Value {
248    Null,
249    Boolean(bool),
250    Number(f64),
251    String(String),
252    BinaryString(Vec<u8>),
253    Regex(String, String),
254    Array(Vec<Value>),
255    SystemArray(Vec<Value>),
256    Set(Vec<Value>),
257    Bag(Vec<Value>),
258    Dict(HashMap<String, Value>),
259    SystemDict(HashMap<String, Value>),
260    PairList(Vec<(String, Value)>),
261    Pair(String, Box<Value>),
262    Function(Rc<FunctionValue>),
263    NativeFunction(Rc<String>),
264    Method(Rc<MethodValue>),
265    Iterator(Rc<RefCell<IteratorState>>),
266    Class(Rc<String>),
267    UserClass(Rc<UserClassValue>),
268    Trait(Rc<TraitValue>),
269    Object(Rc<RefCell<ObjectValue>>),
270    Task(Rc<RefCell<TaskState>>),
271    Channel(Rc<RefCell<ChannelState>>),
272    CancellationSource(Rc<RefCell<CancellationState>>),
273    CancellationToken(Rc<RefCell<CancellationState>>),
274    Shared(Rc<RefCell<Value>>),
275    Ref(Rc<LvalueRef>),
276    AliasRef(Rc<LvalueRef>),
277    WeakFunction(Weak<FunctionValue>),
278    WeakNativeFunction(Weak<String>),
279    WeakMethod(Weak<MethodValue>),
280    WeakIterator(Weak<RefCell<IteratorState>>),
281    WeakClass(Weak<String>),
282    WeakUserClass(Weak<UserClassValue>),
283    WeakTrait(Weak<TraitValue>),
284    WeakObject(Weak<RefCell<ObjectValue>>),
285    WeakTask(Weak<RefCell<TaskState>>),
286    WeakChannel(Weak<RefCell<ChannelState>>),
287    WeakCancellationSource(Weak<RefCell<CancellationState>>),
288    WeakCancellationToken(Weak<RefCell<CancellationState>>),
289    WeakShared(Weak<RefCell<Value>>),
290    WeakRef(Weak<LvalueRef>),
291    WeakAliasRef(Weak<LvalueRef>),
292    WeakStoredScalar(Box<Value>),
293}
294
295struct IteratorState {
296    items: Vec<Value>,
297    index: usize,
298}
299
300#[derive(Clone)]
301struct FunctionValue {
302    name: Option<String>,
303    params: Vec<Parameter>,
304    return_type: Option<String>,
305    body: Rc<RefCell<FunctionBody>>,
306    env: Rc<Environment>,
307    is_async: bool,
308    current_method: Option<Rc<MethodValue>>,
309}
310
311#[derive(Clone)]
312enum FunctionBody {
313    Bodyless,
314    Forward(Rc<FunctionValue>),
315    Block(BlockStatement),
316    Expression(Expression),
317}
318
319struct UserClassValue {
320    name: String,
321    base: Option<ClassBase>,
322    traits: Vec<Rc<TraitValue>>,
323    fields: Vec<FieldSpec>,
324    methods: HashMap<String, Rc<MethodValue>>,
325    static_methods: HashMap<String, Rc<MethodValue>>,
326    nested_classes: HashMap<String, Rc<UserClassValue>>,
327    source_decl: Option<ClassDeclaration>,
328    closure_env: Option<Rc<Environment>>,
329}
330
331#[derive(Clone)]
332struct FieldSpec {
333    name: String,
334    declared_type: Option<String>,
335    mutable: bool,
336    accessors: Vec<String>,
337    default_value: Option<Expression>,
338    is_weak_storage: bool,
339}
340
341struct MethodValue {
342    name: String,
343    params: Vec<Parameter>,
344    return_type: Option<String>,
345    body: BlockStatement,
346    env: Rc<Environment>,
347    #[allow(dead_code)]
348    is_static: bool,
349    is_async: bool,
350    is_bodyless: bool,
351    bound_receiver: Option<Value>,
352    bound_name: Option<String>,
353}
354
355pub(in crate::runtime) enum TaskKind {
356    Resolved,
357    Sleep {
358        deadline: Instant,
359    },
360    Function {
361        function: Rc<FunctionValue>,
362        args: Vec<Value>,
363        named_args: Vec<(String, Value)>,
364        started: bool,
365    },
366    FunctionWaiting {
367        awaited: Rc<RefCell<TaskState>>,
368        frames: Vec<AsyncFrame>,
369        disposition: AwaitDisposition,
370    },
371    Spawn {
372        body: BlockStatement,
373        env: Rc<Environment>,
374        started: bool,
375    },
376    SpawnWaiting {
377        awaited: Rc<RefCell<TaskState>>,
378        frames: Vec<AsyncFrame>,
379        disposition: AwaitDisposition,
380    },
381    All {
382        tasks: Vec<Value>,
383    },
384    Race {
385        tasks: Vec<Value>,
386    },
387    Timeout {
388        deadline: Instant,
389        seconds: f64,
390        task: Value,
391    },
392    ChannelRecv {
393        channel: Rc<RefCell<ChannelState>>,
394    },
395    NativeAsync {
396        cancel_requested: Option<Rc<Cell<bool>>>,
397    },
398}
399
400#[derive(Clone)]
401enum AsyncFrame {
402    Function {
403        statements: Vec<Statement>,
404        index: usize,
405        env: Rc<Environment>,
406        return_type: Option<String>,
407        name: Option<String>,
408    },
409    Block {
410        statements: Vec<Statement>,
411        index: usize,
412        env: Rc<Environment>,
413        cleanup_env: bool,
414    },
415    Do {
416        statements: Vec<Statement>,
417        index: usize,
418        env: Rc<Environment>,
419        cleanup_env: bool,
420        last: Value,
421    },
422}
423
424#[derive(Clone)]
425enum AwaitDisposition {
426    Discard,
427    StoreLast,
428    Return,
429}
430
431enum AsyncPoll {
432    Complete(Value),
433    Await {
434        awaited: Rc<RefCell<TaskState>>,
435        frames: Vec<AsyncFrame>,
436        disposition: AwaitDisposition,
437    },
438}
439
440#[derive(Clone)]
441pub(in crate::runtime) enum TaskOutcome {
442    Fulfilled(Value),
443    Rejected(String),
444    Cancelled(String),
445}
446
447pub(in crate::runtime) struct TaskState {
448    pub(in crate::runtime) status: String,
449    pub(in crate::runtime) kind: TaskKind,
450    pub(in crate::runtime) outcome: Option<TaskOutcome>,
451}
452
453pub(in crate::runtime) struct ChannelState {
454    pub(in crate::runtime) messages: Vec<Value>,
455    pub(in crate::runtime) closed: bool,
456}
457
458pub(in crate::runtime) struct CancellationState {
459    pub(in crate::runtime) cancelled: bool,
460    pub(in crate::runtime) reason: Value,
461    pub(in crate::runtime) watched: Vec<Rc<RefCell<TaskState>>>,
462}
463
464pub(in crate::runtime) enum WorkerFrame {
465    Message(Vec<u8>),
466    Close,
467    Cancel(String),
468}
469
470pub(in crate::runtime) struct WorkerEndpointState {
471    pub(in crate::runtime) sender: mpsc::Sender<WorkerFrame>,
472    pub(in crate::runtime) receiver: mpsc::Receiver<WorkerFrame>,
473    pub(in crate::runtime) queue: Vec<Value>,
474    pub(in crate::runtime) local_closed: bool,
475    pub(in crate::runtime) remote_closed: bool,
476    pub(in crate::runtime) cancelled: bool,
477    pub(in crate::runtime) cancel_requested: Arc<AtomicBool>,
478}
479
480struct TraitValue {
481    name: String,
482    methods: HashMap<String, Rc<MethodValue>>,
483    source_decl: Option<TraitDeclaration>,
484    closure_env: Option<Rc<Environment>>,
485}
486
487struct ObjectValue {
488    class: Rc<UserClassValue>,
489    fields: HashMap<String, Value>,
490    weak_fields: HashSet<String>,
491    builtin_value: Option<Value>,
492}
493
494#[derive(Clone)]
495enum ClassBase {
496    User(Rc<UserClassValue>),
497    Builtin(String),
498}
499
500enum LvalueRef {
501    Expression {
502        env: Rc<Environment>,
503        target: Expression,
504    },
505    ObjectField {
506        object: Weak<RefCell<ObjectValue>>,
507        name: String,
508    },
509}
510
511struct Environment {
512    parent: Option<Rc<Environment>>,
513    bindings: RefCell<HashMap<String, Binding>>,
514}
515
516#[derive(Clone)]
517struct Binding {
518    value: Value,
519    mutable: bool,
520    is_weak_storage: bool,
521}
522
523#[allow(dead_code)]
524#[derive(Clone)]
525struct SimpleRegex {
526    parts: Vec<RegexPart>,
527    case_insensitive: bool,
528}
529
530#[allow(dead_code)]
531#[derive(Clone)]
532enum RegexPart {
533    Literal(String),
534    DigitClassPlus,
535    LowerAlphaClassPlus,
536    Group(Vec<RegexPart>),
537}
538
539#[allow(dead_code)]
540struct RegexMatch {
541    start: usize,
542    end: usize,
543    groups: Vec<String>,
544}
545
546enum ControlFlow {
547    Normal,
548    Return(Value),
549    #[allow(dead_code)]
550    Throw(Value),
551    Continue,
552    Break,
553}
554
555#[derive(Clone, Copy)]
556enum CollectionKind {
557    Array,
558    Set,
559    Bag,
560}
561
562pub fn module_search_roots(include_dirs: Vec<PathBuf>) -> Vec<PathBuf> {
563    let initial_cwd = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
564    let mut roots = include_dirs
565        .into_iter()
566        .map(|path| absolutize_module_path(path, &initial_cwd))
567        .collect::<Vec<_>>();
568
569    roots.extend(source_checkout_module_dirs(&initial_cwd));
570
571    if let Some(zuzulib) = std::env::var_os("ZUZULIB") {
572        roots.extend(
573            std::env::split_paths(&zuzulib).map(|path| absolutize_module_path(path, &initial_cwd)),
574        );
575    }
576
577    if let Some(user_dir) = user_modules_dir() {
578        if user_dir.is_dir() {
579            roots.push(user_dir);
580        }
581    }
582
583    if let Some(system_dir) = system_modules_dir() {
584        if system_dir.is_dir() {
585            roots.push(system_dir);
586        }
587    }
588
589    if let Some(stdlib) = std::env::var_os("ZUZU_STDLIB").filter(|value| !value.is_empty()) {
590        roots.push(absolutize_module_path(PathBuf::from(stdlib), &initial_cwd));
591    } else if let Some(stdlib) = installed_stdlib_modules_dir() {
592        roots.push(stdlib);
593    }
594
595    dedup_paths(roots)
596}
597
598fn source_checkout_module_dirs(start: &Path) -> Vec<PathBuf> {
599    let mut current = start.to_path_buf();
600    loop {
601        let candidates = [
602            current.join("modules"),
603            current.join("languagetests").join("lang").join("modules"),
604            current.join("stdlib").join("modules"),
605            current.join("stdlib").join("test-modules"),
606        ];
607        let roots = candidates
608            .into_iter()
609            .filter(|path| path.is_dir())
610            .collect::<Vec<_>>();
611        if !roots.is_empty() {
612            return roots;
613        }
614        if !current.pop() {
615            break;
616        }
617    }
618    Vec::new()
619}
620
621fn absolutize_module_path(path: PathBuf, base: &Path) -> PathBuf {
622    if path.is_absolute() {
623        path
624    } else {
625        base.join(path)
626    }
627}
628
629fn user_modules_dir() -> Option<PathBuf> {
630    if cfg!(windows) {
631        return std::env::var_os("LOCALAPPDATA")
632            .map(PathBuf::from)
633            .map(|path| path.join("Zuzu").join("modules"));
634    }
635    std::env::var_os("HOME")
636        .map(PathBuf::from)
637        .map(|path| path.join(".zuzu").join("modules"))
638}
639
640fn system_modules_dir() -> Option<PathBuf> {
641    if cfg!(windows) {
642        return std::env::var_os("ProgramData")
643            .map(PathBuf::from)
644            .map(|path| path.join("Zuzu").join("modules"));
645    }
646    Some(PathBuf::from("/var/lib/zuzu/modules"))
647}
648
649fn installed_stdlib_modules_dir() -> Option<PathBuf> {
650    let exe = std::env::current_exe().ok()?;
651    let bin_dir = exe.parent()?;
652    let prefix = if bin_dir.file_name().and_then(|name| name.to_str()) == Some("bin") {
653        bin_dir.parent()?
654    } else {
655        bin_dir
656    };
657    Some(prefix.join("share").join("zuzu-rust").join("modules"))
658}
659
660fn dedup_paths(paths: Vec<PathBuf>) -> Vec<PathBuf> {
661    let mut seen = HashSet::new();
662    let mut out = Vec::new();
663    for path in paths {
664        if seen.insert(path.clone()) {
665            out.push(path);
666        }
667    }
668    out
669}
670
671impl Runtime {
672    pub fn new(module_roots: Vec<PathBuf>) -> Self {
673        Self::with_policy(module_roots, RuntimePolicy::default())
674    }
675
676    pub fn with_policy(module_roots: Vec<PathBuf>, policy: RuntimePolicy) -> Self {
677        Self::with_policy_and_worker_cancel(module_roots, policy, None)
678    }
679
680    pub(in crate::runtime) fn with_policy_and_worker_cancel(
681        module_roots: Vec<PathBuf>,
682        policy: RuntimePolicy,
683        worker_cancel_requested: Option<Arc<AtomicBool>>,
684    ) -> Self {
685        Self {
686            inner: Rc::new(RuntimeInner {
687                module_roots,
688                policy,
689                run_sema: true,
690                infer_types: true,
691                optimizations: OptimizationOptions::default(),
692                module_cache: RefCell::new(HashMap::new()),
693                regex_cache: RefCell::new(HashMap::new()),
694                per_object_trait_class_cache: RefCell::new(HashMap::new()),
695                module_loading: RefCell::new(HashSet::new()),
696                output: RefCell::new(ExecutionOutput::default()),
697                special_props: RefCell::new(vec![HashMap::new()]),
698                thrown_values: RefCell::new(HashMap::new()),
699                next_thrown_id: RefCell::new(0),
700                path_line_cursors: RefCell::new(HashMap::new()),
701                socket_state: RefCell::new(SocketState::default()),
702                current_env_stack: RefCell::new(Vec::new()),
703                current_method_stack: RefCell::new(Vec::new()),
704                signal_handlers: RefCell::new(HashMap::new()),
705                db_state: RefCell::new(self::stdlib::DbState::default()),
706                clib_state: RefCell::new(self::stdlib::ClibState::default()),
707                running_async_functions: RefCell::new(Vec::new()),
708                polling_tasks: RefCell::new(Vec::new()),
709                background_tasks: RefCell::new(Vec::new()),
710                worker_endpoints: RefCell::new(HashMap::new()),
711                next_worker_endpoint_id: RefCell::new(1),
712                worker_cancel_requested,
713                async_executor: AsyncExecutor::new(),
714            }),
715        }
716    }
717
718    pub fn from_repo_root(repo_root: &Path) -> Self {
719        Self::new(module_search_roots(source_checkout_module_dirs(repo_root)))
720    }
721
722    pub fn from_repo_root_with_policy(repo_root: &Path, policy: RuntimePolicy) -> Self {
723        Self::with_policy(
724            module_search_roots(source_checkout_module_dirs(repo_root)),
725            policy,
726        )
727    }
728
729    pub fn with_parse_options(mut self, run_sema: bool, infer_types: bool) -> Self {
730        let inner = Rc::get_mut(&mut self.inner)
731            .expect("parse options must be set before runtime is cloned");
732        inner.run_sema = run_sema;
733        inner.infer_types = infer_types;
734        self
735    }
736
737    pub fn with_optimization_options(mut self, optimizations: OptimizationOptions) -> Self {
738        let inner = Rc::get_mut(&mut self.inner)
739            .expect("optimization options must be set before runtime is cloned");
740        inner.optimizations = optimizations;
741        self
742    }
743
744    pub fn repl_session(&self) -> ReplSession<'_> {
745        let env = Rc::new(Environment::new(None));
746        self.install_builtins(&env);
747        ReplSession { runtime: self, env }
748    }
749
750    #[allow(dead_code)]
751    fn composite_value_ref_target(&self, env: Rc<Environment>, field_name: &str) -> Value {
752        Value::Ref(Rc::new(LvalueRef::Expression {
753            env,
754            target: Expression::DictAccess {
755                line: 0,
756                source_file: None,
757                object: Box::new(Expression::Identifier {
758                    line: 0,
759                    source_file: None,
760                    name: "self".to_owned(),
761                    inferred_type: None,
762                    binding_depth: None,
763                }),
764                key: Box::new(DictKey::Identifier {
765                    line: 0,
766                    source_file: None,
767                    name: field_name.to_owned(),
768                }),
769                inferred_type: None,
770            },
771        }))
772    }
773
774    fn is_ref_backed_composite(&self, value: &Value) -> bool {
775        matches!(
776            value,
777            Value::Array(_)
778                | Value::Set(_)
779                | Value::Bag(_)
780                | Value::Dict(_)
781                | Value::PairList(_)
782                | Value::Pair(_, _)
783                | Value::Shared(_)
784        )
785    }
786
787    fn deref_value(&self, value: &Value) -> Result<Value> {
788        let mut current = value.clone();
789        for _ in 0..32 {
790            match current {
791                value if value.is_weak_value() => {
792                    current = value.resolve_weak_value();
793                }
794                Value::Ref(reference) | Value::AliasRef(reference) => {
795                    current = self.call_ref(Rc::clone(&reference), Vec::new(), Vec::new())?;
796                }
797                Value::Shared(value) => {
798                    current = value.borrow().clone();
799                }
800                _ => return Ok(current),
801            }
802        }
803        Err(ZuzuRustError::runtime(
804            "reference dereference recursion limit reached",
805        ))
806    }
807
808    fn value_is_nullish(&self, value: &Value) -> Result<bool> {
809        self.value_is_nullish_inner(value, 0)
810    }
811
812    fn value_is_nullish_inner(&self, value: &Value, depth: usize) -> Result<bool> {
813        if depth > 32 {
814            return Err(ZuzuRustError::runtime(
815                "reference dereference recursion limit reached",
816            ));
817        }
818        match value {
819            Value::Null => Ok(true),
820            Value::WeakFunction(value) => Ok(value.upgrade().is_none()),
821            Value::WeakNativeFunction(value) => Ok(value.upgrade().is_none()),
822            Value::WeakMethod(value) => Ok(value.upgrade().is_none()),
823            Value::WeakIterator(value) => Ok(value.upgrade().is_none()),
824            Value::WeakClass(value) => Ok(value.upgrade().is_none()),
825            Value::WeakUserClass(value) => Ok(value.upgrade().is_none()),
826            Value::WeakTrait(value) => Ok(value.upgrade().is_none()),
827            Value::WeakObject(value) => Ok(value.upgrade().is_none()),
828            Value::WeakTask(value) => Ok(value.upgrade().is_none()),
829            Value::WeakChannel(value) => Ok(value.upgrade().is_none()),
830            Value::WeakCancellationSource(value) => Ok(value.upgrade().is_none()),
831            Value::WeakCancellationToken(value) => Ok(value.upgrade().is_none()),
832            Value::WeakShared(value) => {
833                let Some(value) = value.upgrade() else {
834                    return Ok(true);
835                };
836                let result = self.value_is_nullish_inner(&value.borrow(), depth + 1);
837                result
838            }
839            Value::WeakRef(value) | Value::WeakAliasRef(value) => {
840                let Some(reference) = value.upgrade() else {
841                    return Ok(true);
842                };
843                let value = self.call_ref(reference, Vec::new(), Vec::new())?;
844                self.value_is_nullish_inner(&value, depth + 1)
845            }
846            Value::WeakStoredScalar(value) => self.value_is_nullish_inner(value, depth + 1),
847            Value::Ref(reference) | Value::AliasRef(reference) => {
848                let value = self.call_ref(Rc::clone(reference), Vec::new(), Vec::new())?;
849                self.value_is_nullish_inner(&value, depth + 1)
850            }
851            Value::Shared(value) => {
852                let result = self.value_is_nullish_inner(&value.borrow(), depth + 1);
853                result
854            }
855            _ => Ok(false),
856        }
857    }
858
859    pub(in crate::runtime) fn normalize_value(&self, value: Value) -> Result<Value> {
860        match value {
861            value if value.is_weak_value() => self.deref_value(&value),
862            Value::AliasRef(_) | Value::Shared(_) => self.deref_value(&value),
863            other => Ok(other),
864        }
865    }
866
867    fn with_current_env<T>(
868        &self,
869        env: Rc<Environment>,
870        f: impl FnOnce() -> Result<T>,
871    ) -> Result<T> {
872        self.current_env_stack.borrow_mut().push(env);
873        let result = f();
874        self.current_env_stack.borrow_mut().pop();
875        result
876    }
877
878    fn current_env(&self) -> Option<Rc<Environment>> {
879        self.current_env_stack.borrow().last().cloned()
880    }
881
882    fn parse_options(&self) -> ParseOptions {
883        ParseOptions::new(self.run_sema, self.infer_types, self.optimizations.clone())
884    }
885
886    fn emit_semantic_warnings(&self, program: &Program) -> Result<()> {
887        if !self.run_sema {
888            return Ok(());
889        }
890        for warning in sema::weak_storage_warnings(program) {
891            self.emit_stderr(&format!("{warning}\n"))?;
892        }
893        Ok(())
894    }
895
896    fn assign_reference(&self, reference: Rc<LvalueRef>, value: Value) -> Result<Value> {
897        self.call_ref(reference, vec![value], Vec::new())
898    }
899
900    fn assign_reference_with_weak_write(
901        &self,
902        reference: Rc<LvalueRef>,
903        value: Value,
904        weak_write: bool,
905    ) -> Result<Value> {
906        self.call_ref(
907            reference,
908            vec![value, Value::Boolean(weak_write)],
909            Vec::new(),
910        )
911    }
912
913    fn maybe_return_trivial_field_getter(
914        &self,
915        object: &Rc<RefCell<ObjectValue>>,
916        method: &Rc<MethodValue>,
917    ) -> Option<Result<Value>> {
918        if !method.params.is_empty() {
919            return None;
920        }
921        let [statement] = method.body.statements.as_slice() else {
922            return None;
923        };
924        let field_name = match statement {
925            Statement::ReturnStatement(node) => match node.argument.as_ref() {
926                Some(Expression::Identifier { name, .. }) => Some(name.as_str()),
927                _ => None,
928            },
929            Statement::ExpressionStatement(node) => match &node.expression {
930                Expression::Identifier { name, .. } => Some(name.as_str()),
931                _ => None,
932            },
933            _ => None,
934        }?;
935        // Only short-circuit when the identifier really is a field of the
936        // object; anything else (e.g. a module global) must go through the
937        // normal call path so the environment chain resolves it.
938        let value = object.borrow().fields.get(field_name).cloned()?;
939        Some(Ok(if value.is_weak_value() {
940            value.resolve_weak_value()
941        } else {
942            value
943        }))
944    }
945
946    pub fn run_script_file(&self, script_path: &Path) -> Result<ExecutionOutput> {
947        self.run_script_file_with_args(script_path, &[])
948    }
949
950    pub fn run_script_file_with_args(
951        &self,
952        script_path: &Path,
953        argv: &[String],
954    ) -> Result<ExecutionOutput> {
955        let source = fs::read_to_string(script_path)?;
956        self.run_script_source_with_args_and_source_file(
957            &source,
958            argv,
959            Some(&script_path.display().to_string()),
960        )
961    }
962
963    pub fn last_output(&self) -> ExecutionOutput {
964        self.output.borrow().clone()
965    }
966
967    pub(crate) fn emit_stdout(&self, text: &str) -> Result<()> {
968        self.output.borrow_mut().stdout.push_str(text);
969        let mut stdout = io::stdout().lock();
970        stdout.write_all(text.as_bytes())?;
971        stdout.flush()?;
972        Ok(())
973    }
974
975    pub(crate) fn emit_stderr(&self, text: &str) -> Result<()> {
976        self.output.borrow_mut().stderr.push_str(text);
977        let mut stderr = io::stderr().lock();
978        stderr.write_all(text.as_bytes())?;
979        stderr.flush()?;
980        Ok(())
981    }
982
983    pub(crate) fn warn_blocking_operation(&self, operation: &str) -> Result<()> {
984        if self.policy.debug_level == 0 || self.polling_tasks.borrow().is_empty() {
985            return Ok(());
986        }
987        self.emit_stderr(&format!(
988            "BlockingOperation: {operation} called while polling async task\n"
989        ))
990    }
991
992    pub fn run_script_source(&self, source: &str) -> Result<ExecutionOutput> {
993        self.run_script_source_with_args(source, &[])
994    }
995
996    pub fn run_script_source_with_args(
997        &self,
998        source: &str,
999        argv: &[String],
1000    ) -> Result<ExecutionOutput> {
1001        self.run_script_source_with_args_and_source_file(source, argv, None)
1002    }
1003
1004    pub fn run_script_source_with_args_and_source_file(
1005        &self,
1006        source: &str,
1007        argv: &[String],
1008        source_file: Option<&str>,
1009    ) -> Result<ExecutionOutput> {
1010        self.async_executor.enter(|| {
1011            self.run_script_source_with_args_and_source_file_inner(source, argv, source_file)
1012        })
1013    }
1014
1015    pub fn load_program_without_main(
1016        &self,
1017        program: &Program,
1018        source_file: Option<&str>,
1019    ) -> Result<LoadedScript> {
1020        self.async_executor
1021            .enter(|| self.load_program_without_main_inner(program, source_file))
1022    }
1023
1024    /// Builds a GTK widget preview for Zuzu GUI XML.
1025    ///
1026    /// The XML is parsed through `std/gui.gui_from_xml`, so pure module
1027    /// behaviour is still exercised normally. The returned pointer is a newly
1028    /// created `GtkWidget`, usually carrying a floating reference like normal
1029    /// GTK widget constructors.
1030    pub fn gui_xml_preview_widget(&self, xml: &str) -> Result<*mut c_void> {
1031        self.async_executor
1032            .enter(|| self.gui_xml_preview_widget_inner(xml))
1033    }
1034
1035    fn gui_xml_preview_widget_inner(&self, xml: &str) -> Result<*mut c_void> {
1036        let source = format!(
1037            "from std/gui import gui_from_xml;\n\
1038            gui_from_xml({});\n",
1039            quote_zuzu_string(xml),
1040        );
1041        let options = self.parse_options();
1042        let program = parse_program_with_compile_options(&source, &options)?;
1043        self.emit_semantic_warnings(&program)?;
1044        let env = Rc::new(Environment::new(None));
1045        self.install_builtins(&env);
1046        let value = self.eval_repl_program(&program, env)?;
1047        stdlib::gui::preview_widget(self, &value)
1048    }
1049
1050    fn run_script_source_with_args_and_source_file_inner(
1051        &self,
1052        source: &str,
1053        argv: &[String],
1054        source_file: Option<&str>,
1055    ) -> Result<ExecutionOutput> {
1056        self.reset_top_level_execution_state();
1057        let options = self.parse_options();
1058        let program =
1059            parse_program_with_compile_options_and_source_file(source, &options, source_file)?;
1060        self.emit_semantic_warnings(&program)?;
1061        let env = Rc::new(Environment::new(None));
1062        self.install_builtins(&env);
1063        self.define_file_const(&env, program.source_file.as_deref(), false);
1064        match self.eval_program(&program, Rc::clone(&env)) {
1065            Err(ZuzuRustError::Thrown { value, .. }) => Err(ZuzuRustError::runtime(format!(
1066                "uncaught exception: {value}"
1067            ))),
1068            Err(err) => Err(err),
1069            Ok(flow) => match flow {
1070                ControlFlow::Normal => {
1071                    self.call_main_if_present(Rc::clone(&env), argv)?;
1072                    self.cancel_background_tasks(Value::String("shutdown".to_owned()));
1073                    Ok(self.output.borrow().clone())
1074                }
1075                ControlFlow::Return(_) => Err(ZuzuRustError::runtime(
1076                    "return is not valid at top-level scope",
1077                )),
1078                ControlFlow::Throw(value) => Err(ZuzuRustError::runtime(format!(
1079                    "uncaught exception: {}",
1080                    value
1081                ))),
1082                ControlFlow::Continue | ControlFlow::Break => Err(ZuzuRustError::runtime(
1083                    "loop control is not valid at top-level scope",
1084                )),
1085            },
1086        }
1087    }
1088
1089    fn load_program_without_main_inner(
1090        &self,
1091        program: &Program,
1092        source_file: Option<&str>,
1093    ) -> Result<LoadedScript> {
1094        self.reset_top_level_execution_state();
1095        self.emit_semantic_warnings(program)?;
1096        let env = Rc::new(Environment::new(None));
1097        self.install_builtins(&env);
1098        self.define_file_const(&env, program.source_file.as_deref().or(source_file), false);
1099        match self.eval_program(program, Rc::clone(&env)) {
1100            Err(ZuzuRustError::Thrown { value, .. }) => Err(ZuzuRustError::runtime(format!(
1101                "uncaught exception: {value}"
1102            ))),
1103            Err(err) => Err(err),
1104            Ok(flow) => match flow {
1105                ControlFlow::Normal => Ok(LoadedScript {
1106                    _runtime: self.clone(),
1107                    env,
1108                }),
1109                ControlFlow::Return(_) => Err(ZuzuRustError::runtime(
1110                    "return is not valid at top-level scope",
1111                )),
1112                ControlFlow::Throw(value) => Err(ZuzuRustError::runtime(format!(
1113                    "uncaught exception: {}",
1114                    value
1115                ))),
1116                ControlFlow::Continue | ControlFlow::Break => Err(ZuzuRustError::runtime(
1117                    "loop control is not valid at top-level scope",
1118                )),
1119            },
1120        }
1121    }
1122
1123    fn reset_top_level_execution_state(&self) {
1124        *self.output.borrow_mut() = ExecutionOutput::default();
1125        let mut special_props = self.special_props.borrow_mut();
1126        special_props.clear();
1127        special_props.push(HashMap::new());
1128        drop(special_props);
1129        self.thrown_values.borrow_mut().clear();
1130        *self.next_thrown_id.borrow_mut() = 0;
1131        self.path_line_cursors.borrow_mut().clear();
1132        self.background_tasks.borrow_mut().clear();
1133        *self.socket_state.borrow_mut() = SocketState::default();
1134    }
1135
1136    fn host_value_to_value(&self, value: HostValue) -> Result<Value> {
1137        match value {
1138            HostValue::Null => Ok(Value::Null),
1139            HostValue::Bool(value) => Ok(Value::Boolean(value)),
1140            HostValue::Number(value) => Ok(Value::Number(value)),
1141            HostValue::String(value) => Ok(Value::String(value)),
1142            HostValue::Binary(value) => Ok(Value::BinaryString(value)),
1143            HostValue::Array(values) => values
1144                .into_iter()
1145                .map(|value| self.host_value_to_value(value))
1146                .collect::<Result<Vec<_>>>()
1147                .map(Value::Array),
1148            HostValue::Dict(values) => values
1149                .into_iter()
1150                .map(|(key, value)| Ok((key, self.host_value_to_value(value)?)))
1151                .collect::<Result<HashMap<_, _>>>()
1152                .map(Value::Dict),
1153            HostValue::PairList(values) => values
1154                .into_iter()
1155                .map(|(key, value)| Ok((key, self.host_value_to_value(value)?)))
1156                .collect::<Result<Vec<_>>>()
1157                .map(Value::PairList),
1158            HostValue::Path(path) => self.construct_builtin_class(
1159                "Path",
1160                vec![Value::String(path.to_string_lossy().to_string())],
1161                Vec::new(),
1162            ),
1163        }
1164    }
1165
1166    fn value_to_host_value(&self, value: Value) -> Result<HostValue> {
1167        let value = self.deref_value(&value)?;
1168        match value {
1169            Value::Null => Ok(HostValue::Null),
1170            Value::Boolean(value) => Ok(HostValue::Bool(value)),
1171            Value::Number(value) => Ok(HostValue::Number(value)),
1172            Value::String(value) => Ok(HostValue::String(value)),
1173            Value::BinaryString(value) => Ok(HostValue::Binary(value)),
1174            Value::Array(values) | Value::SystemArray(values) => values
1175                .into_iter()
1176                .map(|value| self.value_to_host_value(value))
1177                .collect::<Result<Vec<_>>>()
1178                .map(HostValue::Array),
1179            Value::Dict(values) | Value::SystemDict(values) => values
1180                .into_iter()
1181                .map(|(key, value)| Ok((key, self.value_to_host_value(value)?)))
1182                .collect::<Result<HashMap<_, _>>>()
1183                .map(HostValue::Dict),
1184            Value::PairList(values) => values
1185                .into_iter()
1186                .map(|(key, value)| Ok((key, self.value_to_host_value(value)?)))
1187                .collect::<Result<Vec<_>>>()
1188                .map(HostValue::PairList),
1189            Value::Object(object) if object.borrow().class.name == "Path" => {
1190                let path = match object.borrow().fields.get("path") {
1191                    Some(Value::String(path)) => PathBuf::from(path),
1192                    _ => PathBuf::new(),
1193                };
1194                Ok(HostValue::Path(path))
1195            }
1196            other => Err(ZuzuRustError::runtime(format!(
1197                "cannot convert {} to HostValue",
1198                self.typeof_name(&other)
1199            ))),
1200        }
1201    }
1202
1203    fn call_main_if_present(&self, env: Rc<Environment>, argv: &[String]) -> Result<()> {
1204        let Some(callee) = env.get_optional("__main__") else {
1205            return Ok(());
1206        };
1207        let should_await_main = matches!(&callee, Value::Function(function) if function.is_async);
1208        let args = Value::Array(argv.iter().map(|arg| Value::String(arg.clone())).collect());
1209        let result = self.call_value(callee, vec![args], Vec::new())?;
1210        if should_await_main {
1211            let _ = self.await_value(result)?;
1212        }
1213        Ok(())
1214    }
1215
1216    fn eval_program(&self, program: &Program, env: Rc<Environment>) -> Result<ControlFlow> {
1217        self.eval_statements(&program.statements, env)
1218    }
1219
1220    fn eval_repl_program(&self, program: &Program, env: Rc<Environment>) -> Result<Value> {
1221        let mut result = Value::Null;
1222        for statement in &program.statements {
1223            result = self.eval_repl_statement(statement, Rc::clone(&env))?;
1224        }
1225        Ok(result)
1226    }
1227
1228    fn eval_repl_statement(&self, statement: &Statement, env: Rc<Environment>) -> Result<Value> {
1229        match statement {
1230            Statement::VariableDeclaration(node) => {
1231                let value = match node.init.as_ref() {
1232                    Some(init) => self.eval_expression(init, Rc::clone(&env))?,
1233                    None => Value::Null,
1234                };
1235                if node.init.is_some() && node.runtime_typecheck_required != Some(false) {
1236                    self.assert_declared_type(node.declared_type.as_deref(), &value, &node.name)?;
1237                }
1238                env.define_with_storage(
1239                    node.name.clone(),
1240                    value.clone(),
1241                    node.kind != "const",
1242                    node.is_weak_storage,
1243                );
1244                Ok(value)
1245            }
1246            Statement::VariableUnpackDeclaration(node) => {
1247                self.eval_variable_unpack_declaration(node, Rc::clone(&env))
1248            }
1249            Statement::FunctionDeclaration(node) => {
1250                let func = self.make_function_from_decl(node, Rc::clone(&env));
1251                let value = Value::Function(Rc::new(func));
1252                if node.is_predeclared {
1253                    if env.get_here(&node.name).is_some() {
1254                        return Err(ZuzuRustError::runtime(format!(
1255                            "Redeclaration of '{}' in the same scope",
1256                            node.name
1257                        )));
1258                    }
1259                    env.define(node.name.clone(), value.clone(), false);
1260                    return Ok(value);
1261                }
1262                if let Some(Value::Function(existing)) = env.get_here(&node.name) {
1263                    if matches!(*existing.body.borrow(), FunctionBody::Bodyless) {
1264                        *existing.body.borrow_mut() =
1265                            FunctionBody::Forward(Rc::clone(match &value {
1266                                Value::Function(function) => function,
1267                                _ => unreachable!(),
1268                            }));
1269                        return Ok(Value::Function(existing));
1270                    }
1271                }
1272                if env.get_here(&node.name).is_some() {
1273                    return Err(ZuzuRustError::runtime(format!(
1274                        "Redeclaration of '{}' in the same scope",
1275                        node.name
1276                    )));
1277                }
1278                env.define(node.name.clone(), value.clone(), false);
1279                Ok(value)
1280            }
1281            Statement::ClassDeclaration(node) => {
1282                let class = self.make_user_class_from_decl(node, Rc::clone(&env))?;
1283                let value = Value::UserClass(Rc::new(class));
1284                env.define(node.name.clone(), value.clone(), false);
1285                Ok(value)
1286            }
1287            Statement::TraitDeclaration(node) => {
1288                let mut methods = HashMap::new();
1289                for member in &node.body {
1290                    if let ClassMember::Method(method) = member {
1291                        self.install_method_decl(&mut methods, method, Rc::clone(&env))?;
1292                    }
1293                }
1294                let value = Value::Trait(Rc::new(TraitValue {
1295                    name: node.name.clone(),
1296                    methods,
1297                    source_decl: Some(node.clone()),
1298                    closure_env: Some(Rc::clone(&env)),
1299                }));
1300                env.define(node.name.clone(), value.clone(), false);
1301                Ok(value)
1302            }
1303            Statement::ExpressionStatement(node) => self.eval_expression(&node.expression, env),
1304            _ => match self.eval_statement(statement, env)? {
1305                ControlFlow::Normal => Ok(Value::Null),
1306                ControlFlow::Return(_) => Err(ZuzuRustError::runtime(
1307                    "return is not valid at top-level scope",
1308                )),
1309                ControlFlow::Throw(value) => Err(ZuzuRustError::runtime(format!(
1310                    "uncaught exception: {}",
1311                    value
1312                ))),
1313                ControlFlow::Continue | ControlFlow::Break => Err(ZuzuRustError::runtime(
1314                    "loop control is not valid at top-level scope",
1315                )),
1316            },
1317        }
1318    }
1319
1320    fn eval_statements(
1321        &self,
1322        statements: &[Statement],
1323        env: Rc<Environment>,
1324    ) -> Result<ControlFlow> {
1325        for statement in statements {
1326            let flow = self.eval_statement(statement, Rc::clone(&env))?;
1327            if !matches!(flow, ControlFlow::Normal) {
1328                return Ok(flow);
1329            }
1330        }
1331        Ok(ControlFlow::Normal)
1332    }
1333
1334    fn eval_function_statements(
1335        &self,
1336        statements: &[Statement],
1337        env: Rc<Environment>,
1338    ) -> Result<ControlFlow> {
1339        for (index, statement) in statements.iter().enumerate() {
1340            let is_last = index + 1 == statements.len();
1341            if is_last {
1342                if let Statement::ExpressionStatement(node) = statement {
1343                    return Ok(ControlFlow::Return(
1344                        self.eval_expression(&node.expression, env)?,
1345                    ));
1346                }
1347            }
1348            let flow = self.eval_statement(statement, Rc::clone(&env))?;
1349            if !matches!(flow, ControlFlow::Normal) {
1350                return Ok(flow);
1351            }
1352            let do_return = self.get_special_prop("__do_return__");
1353            if !matches!(do_return, Value::Null) {
1354                self.set_special_prop("__do_return__", Value::Null);
1355                return Ok(ControlFlow::Return(do_return));
1356            }
1357        }
1358        Ok(ControlFlow::Normal)
1359    }
1360
1361    fn eval_statement(&self, statement: &Statement, env: Rc<Environment>) -> Result<ControlFlow> {
1362        match statement {
1363            Statement::Block(block) => self.eval_block(block, env),
1364            Statement::VariableDeclaration(node) => {
1365                let value = match node.init.as_ref() {
1366                    Some(init) => self.eval_expression(init, Rc::clone(&env))?,
1367                    None => Value::Null,
1368                };
1369                if node.init.is_some() && node.runtime_typecheck_required != Some(false) {
1370                    self.assert_declared_type(node.declared_type.as_deref(), &value, &node.name)?;
1371                }
1372                env.define_with_storage(
1373                    node.name.clone(),
1374                    value,
1375                    node.kind != "const",
1376                    node.is_weak_storage,
1377                );
1378                Ok(ControlFlow::Normal)
1379            }
1380            Statement::VariableUnpackDeclaration(node) => {
1381                self.eval_variable_unpack_declaration(node, env)?;
1382                Ok(ControlFlow::Normal)
1383            }
1384            Statement::FunctionDeclaration(node) => {
1385                let func = self.make_function_from_decl(node, Rc::clone(&env));
1386                let value = Value::Function(Rc::new(func));
1387                if node.is_predeclared {
1388                    if env.get_here(&node.name).is_some() {
1389                        return Err(ZuzuRustError::runtime(format!(
1390                            "Redeclaration of '{}' in the same scope",
1391                            node.name
1392                        )));
1393                    }
1394                    env.define(node.name.clone(), value, false);
1395                    return Ok(ControlFlow::Normal);
1396                }
1397                if let Some(Value::Function(existing)) = env.get_here(&node.name) {
1398                    if matches!(*existing.body.borrow(), FunctionBody::Bodyless) {
1399                        *existing.body.borrow_mut() =
1400                            FunctionBody::Forward(Rc::clone(match &value {
1401                                Value::Function(function) => function,
1402                                _ => unreachable!(),
1403                            }));
1404                        return Ok(ControlFlow::Normal);
1405                    }
1406                }
1407                if env.get_here(&node.name).is_some() {
1408                    return Err(ZuzuRustError::runtime(format!(
1409                        "Redeclaration of '{}' in the same scope",
1410                        node.name
1411                    )));
1412                }
1413                env.define(node.name.clone(), value, false);
1414                Ok(ControlFlow::Normal)
1415            }
1416            Statement::ClassDeclaration(node) => {
1417                let class = self.make_user_class_from_decl(node, Rc::clone(&env))?;
1418                env.define(node.name.clone(), Value::UserClass(Rc::new(class)), false);
1419                Ok(ControlFlow::Normal)
1420            }
1421            Statement::TraitDeclaration(node) => {
1422                let mut methods = HashMap::new();
1423                for member in &node.body {
1424                    if let ClassMember::Method(method) = member {
1425                        methods.insert(
1426                            method.name.clone(),
1427                            Rc::new(self.make_method_from_decl(method, Rc::clone(&env))),
1428                        );
1429                    }
1430                }
1431                env.define(
1432                    node.name.clone(),
1433                    Value::Trait(Rc::new(TraitValue {
1434                        name: node.name.clone(),
1435                        methods,
1436                        source_decl: Some(node.clone()),
1437                        closure_env: Some(Rc::clone(&env)),
1438                    })),
1439                    false,
1440                );
1441                Ok(ControlFlow::Normal)
1442            }
1443            Statement::ImportDeclaration(node) => {
1444                self.eval_import(node, env)?;
1445                Ok(ControlFlow::Normal)
1446            }
1447            Statement::IfStatement(node) => {
1448                if self.value_is_truthy(&self.eval_expression(&node.test, Rc::clone(&env))?)? {
1449                    self.eval_block(&node.consequent, env)
1450                } else if let Some(alternate) = &node.alternate {
1451                    self.eval_statement(alternate, env)
1452                } else {
1453                    Ok(ControlFlow::Normal)
1454                }
1455            }
1456            Statement::WhileStatement(node) => {
1457                loop {
1458                    if !self.value_is_truthy(&self.eval_expression(&node.test, Rc::clone(&env))?)? {
1459                        break;
1460                    }
1461                    match self.eval_block(&node.body, Rc::clone(&env))? {
1462                        ControlFlow::Normal => {}
1463                        ControlFlow::Continue => continue,
1464                        ControlFlow::Break => break,
1465                        other => return Ok(other),
1466                    }
1467                }
1468                Ok(ControlFlow::Normal)
1469            }
1470            Statement::TryStatement(node) => self.eval_try_statement(node, env),
1471            Statement::ReturnStatement(node) => Ok(ControlFlow::Return(
1472                self.eval_optional_expr(node.argument.as_ref(), env)?,
1473            )),
1474            Statement::LoopControlStatement(node) => match node.keyword.as_str() {
1475                "next" | "continue" => Ok(ControlFlow::Continue),
1476                "last" => Ok(ControlFlow::Break),
1477                _ => Err(ZuzuRustError::runtime(format!(
1478                    "unsupported loop control '{}'",
1479                    node.keyword
1480                ))),
1481            },
1482            Statement::ThrowStatement(node) => {
1483                let value = self.eval_expression(&node.argument, env)?;
1484                self.annotate_exception_metadata(&value, node.source_file.as_deref(), node.line);
1485                match &value {
1486                    Value::String(text) => Err(ZuzuRustError::thrown(text.clone())),
1487                    _ => Err(ZuzuRustError::thrown_with_token(
1488                        self.render_value(&value)?,
1489                        self.store_thrown_value(value)?,
1490                    )),
1491                }
1492            }
1493            Statement::DieStatement(node) => {
1494                let value = self.eval_expression(&node.argument, env)?;
1495                let value =
1496                    self.normalize_die_value(value, node.source_file.as_deref(), node.line)?;
1497                Err(ZuzuRustError::thrown_with_token(
1498                    self.render_value(&value)?,
1499                    self.store_thrown_value(value)?,
1500                ))
1501            }
1502            Statement::PostfixConditionalStatement(node) => {
1503                let test =
1504                    self.value_is_truthy(&self.eval_expression(&node.test, Rc::clone(&env))?)?;
1505                let should_run = if node.keyword == "if" { test } else { !test };
1506                if should_run {
1507                    self.eval_statement(&node.statement, env)
1508                } else {
1509                    Ok(ControlFlow::Normal)
1510                }
1511            }
1512            Statement::KeywordStatement(node) => {
1513                match node.keyword.as_str() {
1514                    "say" => {
1515                        let values = self.eval_arguments(&node.arguments, env)?;
1516                        let line = values
1517                            .iter()
1518                            .map(|value| self.render_value(value))
1519                            .collect::<Result<Vec<_>>>()?
1520                            .join("");
1521                        self.emit_stdout(&format!("{line}\n"))?;
1522                    }
1523                    "print" => {
1524                        let values = self.eval_arguments(&node.arguments, env)?;
1525                        let text = values
1526                            .iter()
1527                            .map(|value| self.render_value(value))
1528                            .collect::<Result<Vec<_>>>()?
1529                            .join("");
1530                        self.emit_stdout(&text)?;
1531                    }
1532                    "warn" => {
1533                        let values = self.eval_arguments(&node.arguments, env)?;
1534                        let text = values
1535                            .iter()
1536                            .map(|value| self.render_value(value))
1537                            .collect::<Result<Vec<_>>>()?
1538                            .join("");
1539                        self.emit_stderr(&format!("{text}\n"))?;
1540                    }
1541                    "debug" => {
1542                        let level = if let Some(expr) = node.arguments.first() {
1543                            self.value_to_number(&self.eval_expression(expr, Rc::clone(&env))?)?
1544                                as u32
1545                        } else {
1546                            0
1547                        };
1548                        if level <= self.policy.debug_level {
1549                            let message = if let Some(expr) = node.arguments.get(1) {
1550                                self.render_value(&self.eval_expression(expr, env)?)?
1551                            } else {
1552                                String::new()
1553                            };
1554                            self.emit_stderr(&format!("{message}\n"))?;
1555                        }
1556                    }
1557                    "assert" => {
1558                        if self.policy.debug_level > 0 {
1559                            let value = if let Some(expr) = node.arguments.first() {
1560                                self.eval_expression(expr, env)?
1561                            } else {
1562                                Value::Null
1563                            };
1564                            if !self.value_is_truthy(&value)? {
1565                                return Err(ZuzuRustError::thrown("Assertion failed"));
1566                            }
1567                        }
1568                    }
1569                    other => {
1570                        return Err(ZuzuRustError::runtime(format!(
1571                            "unsupported keyword statement '{}'",
1572                            other
1573                        )))
1574                    }
1575                }
1576                Ok(ControlFlow::Normal)
1577            }
1578            Statement::ExpressionStatement(node) => {
1579                let _ = self.eval_expression(&node.expression, env)?;
1580                Ok(ControlFlow::Normal)
1581            }
1582            Statement::ForStatement(node) => self.eval_for_statement(node, env),
1583            Statement::SwitchStatement(node) => self.eval_switch_statement(node, env),
1584        }
1585    }
1586
1587    fn eval_variable_unpack_declaration(
1588        &self,
1589        node: &VariableUnpackDeclaration,
1590        env: Rc<Environment>,
1591    ) -> Result<Value> {
1592        let source = self.eval_expression(&node.init, Rc::clone(&env))?;
1593        let source_value = self.deref_value(&source)?;
1594        let mut resolved = Vec::new();
1595        for entry in node.pattern.entries() {
1596            let value = self.resolve_unpack_entry(entry, &source_value, Rc::clone(&env))?;
1597            if entry.runtime_typecheck_required != Some(false) {
1598                self.assert_declared_type(entry.declared_type.as_deref(), &value, &entry.name)?;
1599            }
1600            resolved.push((entry, value));
1601        }
1602        for (entry, value) in resolved {
1603            env.define_with_storage(
1604                entry.name.clone(),
1605                value,
1606                node.kind != "const",
1607                entry.is_weak_storage,
1608            );
1609        }
1610        Ok(source)
1611    }
1612
1613    fn resolve_unpack_entry(
1614        &self,
1615        entry: &DeclarationBindingEntry,
1616        source: &Value,
1617        env: Rc<Environment>,
1618    ) -> Result<Value> {
1619        let key = self.eval_dict_key(&entry.key, Rc::clone(&env))?;
1620        let value = match source {
1621            Value::Dict(map) | Value::SystemDict(map) => map.get(&key).cloned(),
1622            Value::PairList(values) => values
1623                .iter()
1624                .find(|(entry_key, _)| entry_key == &key)
1625                .map(|(_, value)| value.clone()),
1626            other => {
1627                return Err(ZuzuRustError::runtime(format!(
1628                    "Declaration unpacking expects Dict or PairList, got {}",
1629                    other.type_name()
1630                )))
1631            }
1632        };
1633        match value {
1634            Some(value) => Ok(value),
1635            None => match &entry.default_value {
1636                Some(default_value) => self.eval_expression(default_value, env),
1637                None => Ok(Value::Null),
1638            },
1639        }
1640    }
1641
1642    fn eval_block(&self, block: &BlockStatement, env: Rc<Environment>) -> Result<ControlFlow> {
1643        let block_env = if block.needs_lexical_scope {
1644            Rc::new(Environment::new(Some(env)))
1645        } else {
1646            env
1647        };
1648        self.push_special_props_scope();
1649        let result = self.eval_statements(&block.statements, Rc::clone(&block_env));
1650        if block.needs_lexical_scope {
1651            match &result {
1652                Ok(ControlFlow::Return(value)) | Ok(ControlFlow::Throw(value)) => {
1653                    self.cleanup_scope_preserving(&block_env, &[value])?;
1654                }
1655                _ => self.cleanup_scope(&block_env)?,
1656            }
1657        }
1658        self.pop_special_props_scope();
1659        result
1660    }
1661
1662    fn eval_try_statement(&self, node: &TryStatement, env: Rc<Environment>) -> Result<ControlFlow> {
1663        match self.eval_block(&node.body, Rc::clone(&env)) {
1664            Err(ZuzuRustError::Thrown { value, token }) => {
1665                let thrown_value = self.lookup_thrown_value(token.as_deref());
1666                for handler in &node.handlers {
1667                    if !self.catch_clause_matches(
1668                        handler.binding.as_ref(),
1669                        &value,
1670                        thrown_value.as_ref(),
1671                    ) {
1672                        continue;
1673                    }
1674                    let catch_env = Rc::new(Environment::new(Some(Rc::clone(&env))));
1675                    let binding_name = handler
1676                        .binding
1677                        .as_ref()
1678                        .and_then(|binding| binding.name.clone())
1679                        .unwrap_or_else(|| "e".to_owned());
1680                    let caught_value = self.make_catch_binding_value(
1681                        handler.binding.as_ref(),
1682                        &value,
1683                        thrown_value.as_ref(),
1684                    );
1685                    catch_env.define(binding_name, caught_value, true);
1686                    let flow = self.eval_block(&handler.body, catch_env)?;
1687                    return Ok(flow);
1688                }
1689                match token {
1690                    Some(token) => Err(ZuzuRustError::thrown_with_token(value, token)),
1691                    None => Err(ZuzuRustError::thrown(value)),
1692                }
1693            }
1694            Err(err) => {
1695                let rendered = err.to_string();
1696                for handler in &node.handlers {
1697                    if !self.catch_clause_matches(handler.binding.as_ref(), &rendered, None) {
1698                        continue;
1699                    }
1700                    let catch_env = Rc::new(Environment::new(Some(Rc::clone(&env))));
1701                    let binding_name = handler
1702                        .binding
1703                        .as_ref()
1704                        .and_then(|binding| binding.name.clone())
1705                        .unwrap_or_else(|| "e".to_owned());
1706                    let caught_value =
1707                        self.make_catch_binding_value(handler.binding.as_ref(), &rendered, None);
1708                    catch_env.define(binding_name, caught_value, true);
1709                    let flow = self.eval_block(&handler.body, catch_env)?;
1710                    return Ok(flow);
1711                }
1712                Err(err)
1713            }
1714            Ok(ControlFlow::Throw(value)) => {
1715                for handler in &node.handlers {
1716                    if !self.catch_clause_matches(
1717                        handler.binding.as_ref(),
1718                        &value.render(),
1719                        Some(&value),
1720                    ) {
1721                        continue;
1722                    }
1723                    let catch_env = Rc::new(Environment::new(Some(Rc::clone(&env))));
1724                    if let Some(binding) = &handler.binding {
1725                        if let Some(name) = &binding.name {
1726                            catch_env.define(name.clone(), value.clone(), true);
1727                        }
1728                    }
1729                    let flow = self.eval_block(&handler.body, catch_env)?;
1730                    return Ok(flow);
1731                }
1732                Ok(ControlFlow::Throw(value))
1733            }
1734            Ok(other) => Ok(other),
1735        }
1736    }
1737
1738    fn catch_clause_matches(
1739        &self,
1740        binding: Option<&crate::ast::CatchBinding>,
1741        thrown_value: &str,
1742        thrown_runtime_value: Option<&Value>,
1743    ) -> bool {
1744        let Some(binding) = binding else {
1745            return true;
1746        };
1747        let Some(declared_type) = binding.declared_type.as_deref() else {
1748            return true;
1749        };
1750        if declared_type == "Any" {
1751            return true;
1752        }
1753        if let Some(value) = thrown_runtime_value {
1754            return self.value_matches_declared_type(declared_type, value);
1755        }
1756        match declared_type {
1757            "Exception" => true,
1758            "BailOutException" => thrown_value.starts_with("Bail out!"),
1759            "TypeException" => thrown_value.starts_with("TypeException:"),
1760            "CancelledException" => thrown_value.starts_with("CancelledException:"),
1761            "TimeoutException" => thrown_value.starts_with("TimeoutException:"),
1762            "ChannelClosedException" => thrown_value.starts_with("ChannelClosedException:"),
1763            "MarshallingException" => thrown_value.starts_with("MarshallingException:"),
1764            "UnmarshallingException" => thrown_value.starts_with("UnmarshallingException:"),
1765            "ExhaustedException" => {
1766                thrown_value == "ExhaustedException"
1767                    || thrown_value.starts_with("ExhaustedException:")
1768            }
1769            _ => false,
1770        }
1771    }
1772
1773    fn eval_for_statement(&self, node: &ForStatement, env: Rc<Environment>) -> Result<ControlFlow> {
1774        let iterable = self.eval_expression(&node.iterable, Rc::clone(&env))?;
1775        let items = self.iterable_items(iterable)?;
1776
1777        if items.is_empty() {
1778            if let Some(else_block) = &node.else_block {
1779                return self.eval_block(else_block, env);
1780            }
1781            return Ok(ControlFlow::Normal);
1782        }
1783
1784        for item in items {
1785            let loop_env = Rc::new(Environment::new(Some(Rc::clone(&env))));
1786            loop_env.define(
1787                node.variable.clone(),
1788                item,
1789                node.binding_kind.as_deref() != Some("const"),
1790            );
1791            match self.eval_statements(&node.body.statements, loop_env)? {
1792                ControlFlow::Normal => {}
1793                ControlFlow::Continue => continue,
1794                ControlFlow::Break => break,
1795                other => return Ok(other),
1796            }
1797        }
1798        Ok(ControlFlow::Normal)
1799    }
1800
1801    fn eval_switch_statement(
1802        &self,
1803        node: &SwitchStatement,
1804        env: Rc<Environment>,
1805    ) -> Result<ControlFlow> {
1806        let discriminant = self.eval_expression(&node.discriminant, Rc::clone(&env))?;
1807        if let Some(index) = &node.index {
1808            for key in self.switch_index_keys(&discriminant) {
1809                if let Some(entry) = index.iter().find(|entry| entry.key == key) {
1810                    return self.eval_switch_cases_from(node, entry.case_index, env);
1811                }
1812            }
1813        }
1814        let mut matched = false;
1815        for case in &node.cases {
1816            if !matched {
1817                for (index, value) in case.values.iter().enumerate() {
1818                    let operator = case
1819                        .operators
1820                        .get(index)
1821                        .and_then(|value| value.as_deref())
1822                        .or(node.comparator.as_deref());
1823                    if self.switch_matches(&discriminant, value, operator, Rc::clone(&env))? {
1824                        matched = true;
1825                        break;
1826                    }
1827                }
1828            }
1829            if matched {
1830                let case_env = Rc::new(Environment::new(Some(Rc::clone(&env))));
1831                match self.eval_statements(&case.consequent, case_env)? {
1832                    ControlFlow::Normal => return Ok(ControlFlow::Normal),
1833                    ControlFlow::Continue => continue,
1834                    other => return Ok(other),
1835                }
1836            }
1837        }
1838        if matched {
1839            if let Some(default) = &node.default {
1840                let default_env = Rc::new(Environment::new(Some(env)));
1841                return self.eval_statements(default, default_env);
1842            }
1843            return Ok(ControlFlow::Normal);
1844        }
1845        if let Some(default) = &node.default {
1846            let default_env = Rc::new(Environment::new(Some(env)));
1847            return self.eval_statements(default, default_env);
1848        }
1849        Ok(ControlFlow::Normal)
1850    }
1851
1852    fn eval_switch_cases_from(
1853        &self,
1854        node: &SwitchStatement,
1855        start: usize,
1856        env: Rc<Environment>,
1857    ) -> Result<ControlFlow> {
1858        for case in node.cases.iter().skip(start) {
1859            let case_env = Rc::new(Environment::new(Some(Rc::clone(&env))));
1860            match self.eval_statements(&case.consequent, case_env)? {
1861                ControlFlow::Normal => return Ok(ControlFlow::Normal),
1862                ControlFlow::Continue => continue,
1863                other => return Ok(other),
1864            }
1865        }
1866        if let Some(default) = &node.default {
1867            let default_env = Rc::new(Environment::new(Some(env)));
1868            return self.eval_statements(default, default_env);
1869        }
1870        Ok(ControlFlow::Normal)
1871    }
1872
1873    fn switch_index_keys(&self, value: &Value) -> Vec<String> {
1874        let mut keys = Vec::new();
1875        if let Ok(value) = self.deref_value(value) {
1876            match value {
1877                Value::Null => keys.push("n:".to_owned()),
1878                Value::Boolean(value) => keys.push(format!("b:{value}")),
1879                Value::Number(value) => keys.push(format!("f:{value}")),
1880                Value::String(value) => keys.push(format!("s:{value}")),
1881                _ => {}
1882            }
1883        }
1884        if let Ok(text) = self.value_to_operator_string(value) {
1885            keys.push(format!("q:{text}"));
1886            keys.push(format!("qi:{}", text.to_lowercase()));
1887        }
1888        if let Ok(number) = self.value_to_number(value) {
1889            if number.is_finite() && number.fract() == 0.0 {
1890                keys.push(format!("i:{}", number as i64));
1891            }
1892        }
1893        keys
1894    }
1895
1896    fn switch_matches(
1897        &self,
1898        discriminant: &Value,
1899        candidate: &Expression,
1900        comparator: Option<&str>,
1901        env: Rc<Environment>,
1902    ) -> Result<bool> {
1903        let compare_env = Rc::new(Environment::new(Some(env)));
1904        compare_env.define(
1905            "__zuzu_switch_value".to_owned(),
1906            discriminant.clone(),
1907            false,
1908        );
1909        let left = Expression::Identifier {
1910            line: candidate.line(),
1911            source_file: candidate.source_file().map(ToOwned::to_owned),
1912            name: "__zuzu_switch_value".to_owned(),
1913            inferred_type: None,
1914            binding_depth: None,
1915        };
1916        let result = self.eval_binary(comparator.unwrap_or("="), &left, candidate, compare_env)?;
1917        self.value_is_truthy(&result)
1918    }
1919
1920    fn eval_collection_elements(
1921        &self,
1922        elements: &[Expression],
1923        capacity_hint: Option<usize>,
1924        env: Rc<Environment>,
1925        kind: CollectionKind,
1926    ) -> Result<Vec<Value>> {
1927        let mut values = Vec::with_capacity(capacity_hint.unwrap_or(elements.len()));
1928        for element in elements {
1929            let value = self.eval_expression(element, Rc::clone(&env))?;
1930            if matches!(
1931                element,
1932                Expression::Binary { operator, .. } if operator == "..."
1933            ) {
1934                match value {
1935                    Value::Array(items) => values.extend(items),
1936                    other => values.push(other),
1937                }
1938            } else {
1939                values.push(value);
1940            }
1941        }
1942        if matches!(kind, CollectionKind::Set) {
1943            let mut unique = Vec::with_capacity(values.len());
1944            for value in values {
1945                push_unique(&mut unique, value);
1946            }
1947            return Ok(unique);
1948        }
1949        Ok(values)
1950    }
1951
1952    fn eval_import(&self, node: &ImportDeclaration, env: Rc<Environment>) -> Result<()> {
1953        if let Some(condition) = &node.condition {
1954            let test =
1955                self.value_is_truthy(&self.eval_expression(&condition.test, Rc::clone(&env))?)?;
1956            let should_import = if condition.keyword == "if" {
1957                test
1958            } else {
1959                !test
1960            };
1961            if !should_import {
1962                self.bind_null_imports(node, env);
1963                return Ok(());
1964            }
1965        }
1966
1967        let exports = match self.load_module_exports(&node.source) {
1968            Ok(exports) => exports,
1969            Err(_) if node.try_mode => {
1970                self.bind_null_imports(node, env);
1971                return Ok(());
1972            }
1973            Err(err) => return Err(err),
1974        };
1975        if node.import_all {
1976            for (name, value) in exports {
1977                if name.starts_with('_') {
1978                    continue;
1979                }
1980                env.define(name, value, true);
1981            }
1982        } else {
1983            for specifier in &node.specifiers {
1984                let value = exports.get(&specifier.imported).cloned().ok_or_else(|| {
1985                    ZuzuRustError::runtime(format!(
1986                        "module '{}' does not export '{}'",
1987                        node.source, specifier.imported
1988                    ))
1989                })?;
1990                env.define(specifier.local.clone(), value, true);
1991            }
1992        }
1993        Ok(())
1994    }
1995
1996    fn bind_null_imports(&self, node: &ImportDeclaration, env: Rc<Environment>) {
1997        if node.import_all {
1998            return;
1999        }
2000        for specifier in &node.specifiers {
2001            env.define(specifier.local.clone(), Value::Null, false);
2002        }
2003    }
2004
2005    pub(in crate::runtime) fn load_module_exports(
2006        &self,
2007        name: &str,
2008    ) -> Result<HashMap<String, Value>> {
2009        if name.split('/').any(|segment| segment == "..") {
2010            return Err(ZuzuRustError::runtime(
2011                "import module path cannot contain '..' segments",
2012            ));
2013        }
2014        if self.module_denied_as_missing(name) {
2015            return Err(ZuzuRustError::runtime(format!(
2016                "module '{}' not found",
2017                name
2018            )));
2019        }
2020        if self.is_denied_module(name) {
2021            return Err(ZuzuRustError::runtime(format!(
2022                "module '{}' is denied by runtime policy",
2023                name
2024            )));
2025        }
2026        if let Some(cached) = self.module_cache.borrow().get(name) {
2027            return Ok(cached.exports.clone());
2028        }
2029        if self.module_loading.borrow().contains(name) {
2030            return Err(ZuzuRustError::thrown("circular module loading detected"));
2031        }
2032
2033        if name == "std/gui/objects" && self.is_denied("gui") {
2034            return Err(ZuzuRustError::thrown(
2035                "std/gui/objects is denied by runtime policy",
2036            ));
2037        }
2038
2039        if let Some(exports) = self.load_runtime_supported_module(name) {
2040            self.module_cache.borrow_mut().insert(
2041                name.to_owned(),
2042                ModuleRecord {
2043                    exports: exports.clone(),
2044                },
2045            );
2046            return Ok(exports);
2047        }
2048
2049        self.module_loading.borrow_mut().insert(name.to_owned());
2050        let result = (|| {
2051            let path = self.resolve_module_path(name)?;
2052            let source = fs::read_to_string(&path)?;
2053            let source_file = path.display().to_string();
2054            let options = self.parse_options();
2055            let program = parse_program_with_compile_options_and_source_file(
2056                &source,
2057                &options,
2058                Some(&source_file),
2059            )?;
2060            self.emit_semantic_warnings(&program)?;
2061            let env = Rc::new(Environment::new(None));
2062            self.install_builtins(&env);
2063            self.define_file_const(&env, Some(&source_file), true);
2064            match self.eval_program(&program, Rc::clone(&env))? {
2065                ControlFlow::Normal => {}
2066                ControlFlow::Return(_) => {
2067                    return Err(ZuzuRustError::runtime(format!(
2068                        "module '{}' returned from top level",
2069                        name
2070                    )))
2071                }
2072                ControlFlow::Throw(value) => {
2073                    return Err(ZuzuRustError::runtime(format!(
2074                        "module '{}' threw during import: {}",
2075                        name, value
2076                    )))
2077                }
2078                ControlFlow::Continue | ControlFlow::Break => {
2079                    return Err(ZuzuRustError::runtime(format!(
2080                        "module '{}' used loop control at top level",
2081                        name
2082                    )))
2083                }
2084            }
2085
2086            let exports = env.export_public_aliases(Rc::clone(&env));
2087            self.module_cache.borrow_mut().insert(
2088                name.to_owned(),
2089                ModuleRecord {
2090                    exports: exports.clone(),
2091                },
2092            );
2093            Ok(exports)
2094        })();
2095        self.module_loading.borrow_mut().remove(name);
2096        result
2097    }
2098
2099    fn resolve_module_path(&self, name: &str) -> Result<PathBuf> {
2100        for root in &self.module_roots {
2101            for ext in ["zzm", "zzs"] {
2102                let path = root.join(format!("{name}.{ext}"));
2103                if path.exists() {
2104                    return Ok(path);
2105                }
2106            }
2107        }
2108        Err(ZuzuRustError::runtime(format!(
2109            "module '{}' not found",
2110            name
2111        )))
2112    }
2113
2114    pub(super) fn is_denied(&self, capability: &str) -> bool {
2115        if capability == "js" {
2116            return true;
2117        }
2118        self.policy.denied_capabilities.contains(capability)
2119            || matches!(
2120                self.get_special_prop(&format!("deny_{capability}")),
2121                Value::Boolean(true)
2122            )
2123    }
2124
2125    #[allow(dead_code)]
2126    pub(super) fn assert_capability(&self, capability: &str, message: &str) -> Result<()> {
2127        if self.is_denied(capability) {
2128            return Err(ZuzuRustError::runtime(message.to_owned()));
2129        }
2130        Ok(())
2131    }
2132
2133    fn is_denied_module(&self, name: &str) -> bool {
2134        self.policy.denied_modules.contains(name)
2135    }
2136
2137    fn module_denied_as_missing(&self, name: &str) -> bool {
2138        (self.is_denied("fs") && name.starts_with("std/io"))
2139            || (self.is_denied("net") && name.starts_with("std/net"))
2140            || (self.is_denied("net") && name == "std/io/socks")
2141            || (self.is_denied("proc") && name == "std/proc")
2142            || (self.is_denied("db") && name == "std/db")
2143            || (self.is_denied("clib") && name == "std/clib")
2144            || (self.is_denied("js") && name == "javascript")
2145            || (self.is_denied("worker") && name == "std/worker")
2146    }
2147
2148    pub(in crate::runtime) fn push_special_props_scope(&self) {
2149        self.special_props.borrow_mut().push(HashMap::new());
2150    }
2151
2152    pub(in crate::runtime) fn pop_special_props_scope(&self) {
2153        let mut props = self.special_props.borrow_mut();
2154        if props.len() > 1 {
2155            props.pop();
2156        }
2157    }
2158
2159    pub(in crate::runtime) fn is_effectively_denied(&self, capability: &str) -> bool {
2160        self.is_denied(capability)
2161    }
2162
2163    pub(in crate::runtime) fn denial_flag(&self, capability: &str) -> bool {
2164        matches!(capability, "perl" | "js") || self.is_denied(capability)
2165    }
2166
2167    pub(in crate::runtime) fn child_runtime_policy(
2168        &self,
2169        extra_denials: &[(String, bool)],
2170    ) -> RuntimePolicy {
2171        let mut policy = self.policy.clone();
2172        for capability in DENIAL_CAPABILITIES {
2173            if self.denial_flag(capability) {
2174                policy = policy.deny_capability(*capability);
2175            }
2176        }
2177        for (capability, denied) in extra_denials {
2178            if *denied {
2179                policy = policy.deny_capability(capability.clone());
2180            }
2181        }
2182        policy
2183    }
2184
2185    pub(in crate::runtime) fn module_roots_clone(&self) -> Vec<PathBuf> {
2186        self.module_roots.clone()
2187    }
2188
2189    pub(in crate::runtime) fn enter_async_context<T>(&self, f: impl FnOnce() -> T) -> T {
2190        self.async_executor.enter(f)
2191    }
2192
2193    pub(in crate::runtime) fn check_worker_cancelled(&self) -> Result<()> {
2194        if self
2195            .worker_cancel_requested
2196            .as_ref()
2197            .map(|flag| flag.load(Ordering::SeqCst))
2198            .unwrap_or(false)
2199        {
2200            return Err(ZuzuRustError::thrown(
2201                "CancelledException: worker cancelled",
2202            ));
2203        }
2204        Ok(())
2205    }
2206
2207    fn get_special_prop(&self, key: &str) -> Value {
2208        for frame in self.special_props.borrow().iter().rev() {
2209            if let Some(value) = frame.get(key) {
2210                return value.clone();
2211            }
2212        }
2213        Value::Null
2214    }
2215
2216    pub(in crate::runtime) fn set_special_prop(&self, key: &str, value: Value) -> Value {
2217        let mut props = self.special_props.borrow_mut();
2218        if let Some(frame) = props.last_mut() {
2219            frame.insert(key.to_owned(), value.clone());
2220        }
2221        value
2222    }
2223
2224    fn set_special_prop_at_level(&self, level: usize, key: &str, value: Value) -> Value {
2225        let mut props = self.special_props.borrow_mut();
2226        let Some(index) = props.len().checked_sub(1 + level) else {
2227            return value;
2228        };
2229        if let Some(frame) = props.get_mut(index) {
2230            frame.insert(key.to_owned(), value.clone());
2231        }
2232        value
2233    }
2234
2235    fn get_special_prop_at_level(&self, level: usize, key: &str) -> Value {
2236        let props = self.special_props.borrow();
2237        let Some(index) = props.len().checked_sub(1 + level) else {
2238            return Value::Null;
2239        };
2240        props
2241            .get(index)
2242            .and_then(|frame| frame.get(key))
2243            .cloned()
2244            .unwrap_or(Value::Null)
2245    }
2246
2247    pub(in crate::runtime) fn store_thrown_value(&self, value: Value) -> Result<String> {
2248        let mut next_id = self.next_thrown_id.borrow_mut();
2249        *next_id += 1;
2250        let token = format!("thrown:{}", *next_id);
2251        self.thrown_values.borrow_mut().insert(token.clone(), value);
2252        Ok(token)
2253    }
2254
2255    fn lookup_thrown_value(&self, token: Option<&str>) -> Option<Value> {
2256        token.and_then(|key| self.thrown_values.borrow().get(key).cloned())
2257    }
2258
2259    fn load_runtime_supported_module(&self, name: &str) -> Option<HashMap<String, Value>> {
2260        stdlib::load_runtime_supported_module(name)
2261    }
2262
2263    fn current_system_value(&self) -> Value {
2264        Value::SystemDict(HashMap::from([
2265            ("runtime".to_owned(), Value::String("zuzu-rust".to_owned())),
2266            ("language_version".to_owned(), Value::Number(0.0)),
2267            (
2268                "runtime_version".to_owned(),
2269                Value::String(env!("CARGO_PKG_VERSION").to_owned()),
2270            ),
2271            (
2272                "platform".to_owned(),
2273                Value::String(std::env::consts::OS.to_owned()),
2274            ),
2275            (
2276                "inc".to_owned(),
2277                Value::SystemArray(
2278                    self.module_roots
2279                        .iter()
2280                        .map(|path| Value::String(path.to_string_lossy().into_owned()))
2281                        .collect(),
2282                ),
2283            ),
2284            ("deny_fs".to_owned(), Value::Boolean(self.is_denied("fs"))),
2285            ("deny_net".to_owned(), Value::Boolean(self.is_denied("net"))),
2286            ("deny_perl".to_owned(), Value::Boolean(true)),
2287            ("deny_js".to_owned(), Value::Boolean(true)),
2288            (
2289                "deny_proc".to_owned(),
2290                Value::Boolean(self.is_denied("proc")),
2291            ),
2292            ("deny_db".to_owned(), Value::Boolean(self.is_denied("db"))),
2293            (
2294                "deny_clib".to_owned(),
2295                Value::Boolean(self.is_denied("clib")),
2296            ),
2297            ("deny_gui".to_owned(), Value::Boolean(self.is_denied("gui"))),
2298            (
2299                "deny_worker".to_owned(),
2300                Value::Boolean(self.is_denied("worker")),
2301            ),
2302        ]))
2303    }
2304
2305    fn make_function_from_decl(
2306        &self,
2307        node: &FunctionDeclaration,
2308        env: Rc<Environment>,
2309    ) -> FunctionValue {
2310        FunctionValue {
2311            name: Some(node.name.clone()),
2312            params: node.params.clone(),
2313            return_type: node.return_type.clone(),
2314            body: Rc::new(RefCell::new(if node.is_predeclared {
2315                FunctionBody::Bodyless
2316            } else {
2317                FunctionBody::Block(node.body.clone())
2318            })),
2319            env,
2320            is_async: node.is_async,
2321            current_method: None,
2322        }
2323    }
2324
2325    fn make_user_class_from_decl(
2326        &self,
2327        node: &ClassDeclaration,
2328        env: Rc<Environment>,
2329    ) -> Result<UserClassValue> {
2330        let base = match &node.base {
2331            Some(name) => match env.get(name)? {
2332                Value::UserClass(class) => Some(ClassBase::User(class)),
2333                Value::Class(name) => Some(ClassBase::Builtin(name.as_ref().clone())),
2334                _ => return Err(ZuzuRustError::runtime(format!("'{}' is not a class", name))),
2335            },
2336            None => None,
2337        };
2338
2339        let class_env = Rc::new(Environment::new(Some(Rc::clone(&env))));
2340        let mut fields = Vec::new();
2341        let mut nested_classes = HashMap::new();
2342        for member in &node.body {
2343            match member {
2344                ClassMember::Field(field) => fields.push(self.make_field_spec(field)),
2345                ClassMember::Class(class) => {
2346                    let mut nested_class =
2347                        self.make_user_class_from_decl(class, Rc::clone(&class_env))?;
2348                    nested_class.name = format!("{}{{\"{}\"}}", node.name, class.name);
2349                    let nested = Rc::new(nested_class);
2350                    class_env.define(
2351                        class.name.clone(),
2352                        Value::UserClass(Rc::clone(&nested)),
2353                        false,
2354                    );
2355                    nested_classes.insert(class.name.clone(), nested);
2356                }
2357                ClassMember::Method(_) | ClassMember::Trait(_) => {}
2358            }
2359        }
2360
2361        let mut methods = HashMap::new();
2362        let mut static_methods = HashMap::new();
2363        for member in &node.body {
2364            match member {
2365                ClassMember::Method(method) => {
2366                    if method.is_static {
2367                        self.install_method_decl(
2368                            &mut static_methods,
2369                            method,
2370                            Rc::clone(&class_env),
2371                        )?;
2372                    } else {
2373                        self.install_method_decl(&mut methods, method, Rc::clone(&class_env))?;
2374                    }
2375                }
2376                ClassMember::Field(_) | ClassMember::Class(_) | ClassMember::Trait(_) => {}
2377            }
2378        }
2379
2380        let mut traits = Vec::new();
2381        for trait_name in &node.traits {
2382            match env.get(trait_name)? {
2383                Value::Trait(trait_value) => traits.push(trait_value),
2384                _ => {
2385                    return Err(ZuzuRustError::runtime(format!(
2386                        "'{}' is not a trait",
2387                        trait_name
2388                    )))
2389                }
2390            }
2391        }
2392
2393        Ok(UserClassValue {
2394            name: node.name.clone(),
2395            base,
2396            traits,
2397            fields,
2398            methods,
2399            static_methods,
2400            nested_classes,
2401            source_decl: Some(node.clone()),
2402            closure_env: Some(env),
2403        })
2404    }
2405
2406    fn make_field_spec(&self, node: &FieldDeclaration) -> FieldSpec {
2407        FieldSpec {
2408            name: node.name.clone(),
2409            declared_type: node.declared_type.clone(),
2410            mutable: node.kind != "const",
2411            accessors: node.accessors.clone(),
2412            default_value: node.default_value.clone(),
2413            is_weak_storage: node.is_weak_storage,
2414        }
2415    }
2416
2417    fn make_method_from_decl(&self, node: &MethodDeclaration, env: Rc<Environment>) -> MethodValue {
2418        MethodValue {
2419            name: node.name.clone(),
2420            params: node.params.clone(),
2421            return_type: node.return_type.clone(),
2422            body: node.body.clone(),
2423            env,
2424            is_static: node.is_static,
2425            is_async: node.is_async,
2426            is_bodyless: node.is_predeclared,
2427            bound_receiver: None,
2428            bound_name: None,
2429        }
2430    }
2431
2432    fn install_method_decl(
2433        &self,
2434        methods: &mut HashMap<String, Rc<MethodValue>>,
2435        node: &MethodDeclaration,
2436        env: Rc<Environment>,
2437    ) -> Result<()> {
2438        if let Some(existing) = methods.get(&node.name) {
2439            if existing.is_bodyless && !node.is_predeclared {
2440                methods.insert(
2441                    node.name.clone(),
2442                    Rc::new(self.make_method_from_decl(node, env)),
2443                );
2444                return Ok(());
2445            }
2446            return Err(ZuzuRustError::runtime(format!(
2447                "Redeclaration of '{}' in the same scope",
2448                node.name
2449            )));
2450        }
2451        methods.insert(
2452            node.name.clone(),
2453            Rc::new(self.make_method_from_decl(node, env)),
2454        );
2455        Ok(())
2456    }
2457
2458    fn function_body_for_method(&self, method: &MethodValue) -> FunctionBody {
2459        if method.is_bodyless {
2460            FunctionBody::Bodyless
2461        } else {
2462            FunctionBody::Block(method.body.clone())
2463        }
2464    }
2465
2466    fn install_builtins(&self, env: &Environment) {
2467        for name in [
2468            "Any",
2469            "Class",
2470            "Null",
2471            "Object",
2472            "Collection",
2473            "Boolean",
2474            "Number",
2475            "String",
2476            "BinaryString",
2477            "Regexp",
2478            "Function",
2479            "Pair",
2480            "PairList",
2481            "Array",
2482            "Bag",
2483            "Set",
2484            "Dict",
2485            "ExhaustedException",
2486            "TypeException",
2487            "CancelledException",
2488            "TimeoutException",
2489            "ChannelClosedException",
2490        ] {
2491            env.define(
2492                name.to_owned(),
2493                Value::builtin_class(name.to_owned()),
2494                false,
2495            );
2496        }
2497        env.define(
2498            "Exception".to_owned(),
2499            Value::UserClass(Rc::new(UserClassValue {
2500                name: "Exception".to_owned(),
2501                base: None,
2502                traits: Vec::new(),
2503                fields: exception_field_specs(),
2504                methods: HashMap::new(),
2505                static_methods: HashMap::new(),
2506                nested_classes: HashMap::new(),
2507                source_decl: None,
2508                closure_env: None,
2509            })),
2510            false,
2511        );
2512        env.define(
2513            "DEBUG".to_owned(),
2514            Value::Number(self.policy.debug_level as f64),
2515            false,
2516        );
2517        for name in ["to_binary", "to_string"] {
2518            env.define(
2519                name.to_owned(),
2520                Value::native_function(name.to_owned()),
2521                false,
2522            );
2523        }
2524        env.define("__global__".to_owned(), Value::Dict(HashMap::new()), true);
2525        env.define("__system__".to_owned(), self.current_system_value(), false);
2526    }
2527
2528    fn file_value_for_source(&self, source_file: Option<&str>, force_absolute: bool) -> Value {
2529        let Some(source_file) = source_file else {
2530            return Value::Null;
2531        };
2532        if self.is_denied("fs") || source_file.is_empty() || source_file.starts_with('<') {
2533            return Value::Null;
2534        }
2535        let mut path = PathBuf::from(source_file);
2536        if force_absolute && !path.is_absolute() {
2537            let base = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
2538            path = absolutize_module_path(path, &base);
2539        }
2540        stdlib::path_value(path)
2541    }
2542
2543    fn define_file_const(
2544        &self,
2545        env: &Environment,
2546        source_file: Option<&str>,
2547        force_absolute: bool,
2548    ) {
2549        env.define(
2550            "__file__".to_owned(),
2551            self.file_value_for_source(source_file, force_absolute),
2552            false,
2553        );
2554    }
2555
2556    fn eval_arguments(&self, arguments: &[Expression], env: Rc<Environment>) -> Result<Vec<Value>> {
2557        arguments
2558            .iter()
2559            .map(|argument| self.eval_expression(argument, Rc::clone(&env)))
2560            .collect()
2561    }
2562
2563    fn eval_optional_expr(&self, expr: Option<&Expression>, env: Rc<Environment>) -> Result<Value> {
2564        match expr {
2565            Some(expr) => self.eval_expression(expr, env),
2566            None => Ok(Value::Null),
2567        }
2568    }
2569
2570    fn eval_expression(&self, expr: &Expression, env: Rc<Environment>) -> Result<Value> {
2571        match expr {
2572            Expression::Identifier {
2573                name,
2574                binding_depth,
2575                ..
2576            } => {
2577                if name == "__system__" {
2578                    return Ok(self.current_system_value());
2579                }
2580                let value = env.get_resolved(*binding_depth, name)?;
2581                match value {
2582                    Value::AliasRef(reference) => self.call_ref(reference, Vec::new(), Vec::new()),
2583                    other => Ok(other),
2584                }
2585            }
2586            Expression::NumberLiteral { value, .. } => {
2587                Ok(Value::Number(value.parse::<f64>().map_err(|_| {
2588                    ZuzuRustError::runtime(format!("invalid number literal '{}'", value))
2589                })?))
2590            }
2591            Expression::StringLiteral { value, .. } => Ok(Value::String(value.clone())),
2592            Expression::BinaryStringLiteral { bytes, .. } => Ok(Value::BinaryString(bytes.clone())),
2593            Expression::RegexLiteral {
2594                pattern,
2595                parts,
2596                flags,
2597                cache_key,
2598                ..
2599            } => {
2600                if parts.is_empty()
2601                    && cache_key.is_some()
2602                    && self.optimizations.enables(OptimizationPass::RegexCache)
2603                {
2604                    let _ = self.compile_regex(pattern, flags)?;
2605                }
2606                let pattern = if parts.is_empty() {
2607                    pattern.clone()
2608                } else {
2609                    self.render_template_parts(parts, Rc::clone(&env))?
2610                };
2611                Ok(Value::Regex(pattern, flags.clone()))
2612            }
2613            Expression::BooleanLiteral { value, .. } => Ok(Value::Boolean(*value)),
2614            Expression::NullLiteral { .. } => Ok(Value::Null),
2615            Expression::ArrayLiteral {
2616                elements,
2617                capacity_hint,
2618                ..
2619            } => Ok(Value::Array(
2620                self.eval_collection_elements(
2621                    elements,
2622                    *capacity_hint,
2623                    env,
2624                    CollectionKind::Array,
2625                )?
2626                .into_iter()
2627                .map(Value::into_shared_if_composite)
2628                .collect(),
2629            )),
2630            Expression::SetLiteral {
2631                elements,
2632                capacity_hint,
2633                ..
2634            } => {
2635                let mut values = Vec::with_capacity(capacity_hint.unwrap_or(elements.len()));
2636                for value in self.eval_collection_elements(
2637                    elements,
2638                    *capacity_hint,
2639                    env,
2640                    CollectionKind::Set,
2641                )? {
2642                    push_unique(&mut values, value.into_shared_if_composite());
2643                }
2644                Ok(Value::Set(values))
2645            }
2646            Expression::BagLiteral {
2647                elements,
2648                capacity_hint,
2649                ..
2650            } => Ok(Value::Bag(
2651                self.eval_collection_elements(elements, *capacity_hint, env, CollectionKind::Bag)?
2652                    .into_iter()
2653                    .map(Value::into_shared_if_composite)
2654                    .collect(),
2655            )),
2656            Expression::DictLiteral {
2657                entries,
2658                capacity_hint,
2659                ..
2660            } => {
2661                let mut map = HashMap::with_capacity(capacity_hint.unwrap_or(entries.len()));
2662                for entry in entries {
2663                    let key = self.eval_dict_key(&entry.key, Rc::clone(&env))?;
2664                    let value = self.eval_expression(&entry.value, Rc::clone(&env))?;
2665                    map.insert(key, value.into_shared_if_composite());
2666                }
2667                Ok(Value::Dict(map))
2668            }
2669            Expression::PairListLiteral {
2670                entries,
2671                capacity_hint,
2672                ..
2673            } => {
2674                let mut values = Vec::with_capacity(capacity_hint.unwrap_or(entries.len()));
2675                for entry in entries {
2676                    let key = self.eval_dict_key(&entry.key, Rc::clone(&env))?;
2677                    let value = self.eval_expression(&entry.value, Rc::clone(&env))?;
2678                    values.push((key, value.into_shared_if_composite()));
2679                }
2680                Ok(Value::PairList(values))
2681            }
2682            Expression::TemplateLiteral { parts, .. } => {
2683                Ok(Value::String(self.render_template_parts(parts, env)?))
2684            }
2685            Expression::Unary {
2686                operator,
2687                argument,
2688                traits,
2689                ..
2690            } => match operator.as_str() {
2691                "new" => self.eval_new_expression(argument, traits, env),
2692                "not" | "!" | "¬" => Ok(Value::Boolean(
2693                    !self.value_is_truthy(&self.eval_expression(argument, env)?)?,
2694                )),
2695                "+" => Ok(Value::Number(
2696                    self.value_to_number(&self.eval_expression(argument, env)?)?,
2697                )),
2698                "-" => Ok(Value::Number(
2699                    -self.value_to_number(&self.eval_expression(argument, env)?)?,
2700                )),
2701                "abs" => Ok(Value::Number(
2702                    self.value_to_number(&self.eval_expression(argument, env)?)?
2703                        .abs(),
2704                )),
2705                "sqrt" | "√" => Ok(Value::Number(
2706                    self.value_to_number(&self.eval_expression(argument, env)?)?
2707                        .sqrt(),
2708                )),
2709                "floor" => Ok(Value::Number(
2710                    self.value_to_number(&self.eval_expression(argument, env)?)?
2711                        .floor(),
2712                )),
2713                "ceil" => Ok(Value::Number(
2714                    self.value_to_number(&self.eval_expression(argument, env)?)?
2715                        .ceil(),
2716                )),
2717                "round" => Ok(Value::Number(
2718                    self.value_to_number(&self.eval_expression(argument, env)?)?
2719                        .round(),
2720                )),
2721                "int" => Ok(Value::Number(
2722                    self.value_to_number(&self.eval_expression(argument, env)?)?
2723                        .trunc(),
2724                )),
2725                "uc" => Ok(Value::String(
2726                    self.value_to_operator_string(&self.eval_expression(argument, env)?)?
2727                        .to_uppercase(),
2728                )),
2729                "lc" => Ok(Value::String(
2730                    self.value_to_operator_string(&self.eval_expression(argument, env)?)?
2731                        .to_lowercase(),
2732                )),
2733                "length" => Ok(Value::Number(
2734                    match self.eval_expression(argument, env)? {
2735                        Value::BinaryString(bytes) => bytes.len() as f64,
2736                        value => self.value_to_operator_string(&value)?.chars().count() as f64,
2737                    },
2738                )),
2739                "typeof" => Ok(Value::String(
2740                    self.typeof_name(&self.eval_expression(argument, env)?),
2741                )),
2742                "~" => {
2743                    let value = self.eval_expression(argument, env)?;
2744                    match value {
2745                        Value::BinaryString(bytes) => Ok(Value::BinaryString(
2746                            bytes.into_iter().map(|byte| !byte).collect(),
2747                        )),
2748                        _ => Ok(Value::Number(
2749                            !(self.value_to_number(&value)? as i64) as f64,
2750                        )),
2751                    }
2752                }
2753                "\\" if matches!(argument.as_ref(), Expression::Binary { operator, .. } if is_path_operator(operator)) => {
2754                    self.eval_path_ref(argument, env)
2755                }
2756                "\\" => Ok(Value::Ref(Rc::new(LvalueRef::Expression {
2757                    env,
2758                    target: (**argument).clone(),
2759                }))),
2760                "++" if matches!(argument.as_ref(), Expression::Binary { operator, .. } if is_path_operator(operator)) => {
2761                    self.eval_path_update(argument, env, 1.0, true)
2762                }
2763                "--" if matches!(argument.as_ref(), Expression::Binary { operator, .. } if is_path_operator(operator)) => {
2764                    self.eval_path_update(argument, env, -1.0, true)
2765                }
2766                "++" => self.update_lvalue(argument, env, |value| {
2767                    Ok(Value::Number(self.value_to_number(&value)? + 1.0))
2768                }),
2769                "--" => self.update_lvalue(argument, env, |value| {
2770                    Ok(Value::Number(self.value_to_number(&value)? - 1.0))
2771                }),
2772                other => Err(ZuzuRustError::runtime(format!(
2773                    "unsupported unary operator '{}'",
2774                    other
2775                ))),
2776            },
2777            Expression::Binary {
2778                operator,
2779                left,
2780                right,
2781                ..
2782            } => self.eval_binary(operator, left, right, env),
2783            Expression::Ternary {
2784                test,
2785                consequent,
2786                alternate,
2787                ..
2788            } => {
2789                if self.value_is_truthy(&self.eval_expression(test, Rc::clone(&env))?)? {
2790                    self.eval_expression(consequent, env)
2791                } else {
2792                    self.eval_expression(alternate, env)
2793                }
2794            }
2795            Expression::DefinedOr { left, right, .. } => {
2796                let left_value = self.eval_expression(left, Rc::clone(&env))?;
2797                if self.value_is_nullish(&left_value)? {
2798                    self.eval_expression(right, env)
2799                } else {
2800                    Ok(left_value)
2801                }
2802            }
2803            Expression::Assignment {
2804                operator,
2805                left,
2806                right,
2807                is_weak_write,
2808                ..
2809            } => {
2810                if operator == "~=" {
2811                    if let Expression::Binary {
2812                        operator: path_operator,
2813                        left: path_left,
2814                        right: path_right,
2815                        ..
2816                    } = left.as_ref()
2817                    {
2818                        if is_path_operator(path_operator) {
2819                            let payload = self.build_path_regex_payload(right, Rc::clone(&env))?;
2820                            return self.assign_path_target(
2821                                path_operator,
2822                                path_left,
2823                                path_right,
2824                                operator,
2825                                payload,
2826                                false,
2827                                env,
2828                            );
2829                        }
2830                    }
2831                }
2832                if operator == "~=" {
2833                    let current = self.eval_expression(left, Rc::clone(&env))?;
2834                    let replacement =
2835                        self.apply_regex_replacement(current, right, Rc::clone(&env))?;
2836                    self.assign_lvalue(left, replacement, false, env)
2837                } else {
2838                    let right_value = self.eval_expression(right, Rc::clone(&env))?;
2839                    self.assign(operator, left, right_value, *is_weak_write, env)
2840                }
2841            }
2842            Expression::Call {
2843                callee, arguments, ..
2844            } => match callee.as_ref() {
2845                Expression::MemberAccess { object, member, .. } => {
2846                    self.invoke_method_expression(object, member, arguments, env)
2847                }
2848                _ => {
2849                    let callee = self.eval_expression(callee, Rc::clone(&env))?;
2850                    let (values, named_args) =
2851                        self.eval_call_arguments(arguments, Rc::clone(&env))?;
2852                    self.with_current_env(env, || self.call_value(callee, values, named_args))
2853                }
2854            },
2855            Expression::DynamicMemberCall {
2856                object,
2857                member,
2858                arguments,
2859                ..
2860            } => {
2861                let receiver = self.eval_expression(object, Rc::clone(&env))?;
2862                let member_value = self.eval_expression(member, Rc::clone(&env))?;
2863                let method_name = match member_value {
2864                    Value::Method(method) => method.name.clone(),
2865                    other => self.render_value(&other)?,
2866                };
2867                let (values, named_args) =
2868                    self.eval_method_call_arguments(arguments, Rc::clone(&env))?;
2869                let mut receiver = receiver;
2870                self.call_method_named(&mut receiver, &method_name, &values, named_args)
2871            }
2872            Expression::MemberAccess { object, member, .. } => {
2873                let mut object = self.eval_expression(object, env)?;
2874                self.call_method(&mut object, member, &[])
2875            }
2876            Expression::Index { object, index, .. } => {
2877                let object = self.eval_expression(object, Rc::clone(&env))?;
2878                let index = self.eval_expression(index, env)?;
2879                self.eval_index(object, index)
2880            }
2881            Expression::Slice {
2882                object, start, end, ..
2883            } => {
2884                let object = self.eval_expression(object, Rc::clone(&env))?;
2885                let start = self.eval_optional_expr(start.as_deref(), Rc::clone(&env))?;
2886                let end = self.eval_optional_expr(end.as_deref(), env)?;
2887                self.eval_slice(object, start, end)
2888            }
2889            Expression::DictAccess { object, key, .. } => {
2890                let object = self.deref_value(&self.eval_expression(object, Rc::clone(&env))?)?;
2891                let key = self.eval_dict_key(key, env)?;
2892                match object {
2893                    Value::Dict(map) | Value::SystemDict(map) => {
2894                        Ok(map.get(&key).cloned().unwrap_or(Value::Null))
2895                    }
2896                    Value::Pair(pair_key, value) => Ok(if key == "pair" {
2897                        Value::Array(vec![Value::String(pair_key), *value])
2898                    } else {
2899                        Value::Null
2900                    }),
2901                    Value::PairList(values) => Ok(values
2902                        .iter()
2903                        .find(|(entry_key, _)| entry_key == &key)
2904                        .map(|(_, value)| value.clone())
2905                        .unwrap_or(Value::Null)),
2906                    Value::Object(object) => Ok(object
2907                        .borrow()
2908                        .fields
2909                        .get(&key)
2910                        .cloned()
2911                        .or_else(|| {
2912                            self.find_method(&object.borrow().class, &key)
2913                                .and_then(|_| {
2914                                    self.marshal_bind_method(
2915                                        Value::Object(Rc::clone(&object)),
2916                                        &key,
2917                                    )
2918                                    .ok()
2919                                })
2920                        })
2921                        .or_else(|| {
2922                            object
2923                                .borrow()
2924                                .class
2925                                .nested_classes
2926                                .get(&key)
2927                                .map(|class| Value::UserClass(Rc::clone(class)))
2928                        })
2929                        .unwrap_or(Value::Null)),
2930                    Value::UserClass(class) => Ok(class
2931                        .methods
2932                        .get(&key)
2933                        .cloned()
2934                        .map(Value::Method)
2935                        .or_else(|| class.static_methods.get(&key).cloned().map(Value::Method))
2936                        .or_else(|| {
2937                            class
2938                                .nested_classes
2939                                .get(&key)
2940                                .map(|nested| Value::UserClass(Rc::clone(nested)))
2941                        })
2942                        .unwrap_or(Value::Null)),
2943                    _ => Err(ZuzuRustError::runtime(
2944                        "dict access requires a Dict or object value",
2945                    )),
2946                }
2947            }
2948            Expression::PostfixUpdate {
2949                operator, argument, ..
2950            } => {
2951                if matches!(argument.as_ref(), Expression::Binary { operator, .. } if is_path_operator(operator))
2952                {
2953                    return self.eval_path_update(
2954                        argument,
2955                        env,
2956                        if operator == "++" { 1.0 } else { -1.0 },
2957                        false,
2958                    );
2959                }
2960                let previous = self.eval_expression(argument, Rc::clone(&env))?;
2961                let delta = match operator.as_str() {
2962                    "++" => 1.0,
2963                    "--" => -1.0,
2964                    other => {
2965                        return Err(ZuzuRustError::runtime(format!(
2966                            "unsupported postfix operator '{}'",
2967                            other
2968                        )))
2969                    }
2970                };
2971                let _ = self.update_lvalue(argument, env, |value| {
2972                    Ok(Value::Number(self.value_to_number(&value)? + delta))
2973                })?;
2974                Ok(previous)
2975            }
2976            Expression::FunctionExpression {
2977                params,
2978                return_type,
2979                body,
2980                is_async,
2981                ..
2982            } => Ok(Value::Function(Rc::new(FunctionValue {
2983                name: None,
2984                params: params.clone(),
2985                return_type: return_type.clone(),
2986                body: Rc::new(RefCell::new(FunctionBody::Block(body.clone()))),
2987                env,
2988                is_async: *is_async,
2989                current_method: None,
2990            }))),
2991            Expression::Lambda {
2992                params,
2993                body,
2994                is_async,
2995                ..
2996            } => Ok(Value::Function(Rc::new(FunctionValue {
2997                name: None,
2998                params: params.clone(),
2999                return_type: None,
3000                body: Rc::new(RefCell::new(FunctionBody::Expression((**body).clone()))),
3001                env,
3002                is_async: *is_async,
3003                current_method: None,
3004            }))),
3005            Expression::LetExpression {
3006                kind,
3007                name,
3008                init,
3009                is_weak_storage,
3010                ..
3011            } => {
3012                let value = match init {
3013                    Some(init) => self.eval_expression(init, Rc::clone(&env))?,
3014                    None => Value::Null,
3015                };
3016                env.define_with_storage(
3017                    name.clone(),
3018                    value.clone(),
3019                    kind != "const",
3020                    *is_weak_storage,
3021                );
3022                Ok(value)
3023            }
3024            Expression::DoExpression { body, .. } => self.eval_do_expression(body, env),
3025            Expression::AwaitExpression { body, .. } => {
3026                let value = self.eval_do_expression(body, env)?;
3027                self.await_value(value)
3028            }
3029            Expression::SpawnExpression { body, .. } => {
3030                let task = Rc::new(RefCell::new(TaskState {
3031                    status: "pending".to_owned(),
3032                    kind: TaskKind::Spawn {
3033                        body: body.clone(),
3034                        env,
3035                        started: false,
3036                    },
3037                    outcome: None,
3038                }));
3039                self.background_tasks.borrow_mut().push(Rc::clone(&task));
3040                self.schedule_task_driver(Rc::clone(&task));
3041                Ok(Value::Task(task))
3042            }
3043            Expression::TryExpression { body, handlers, .. } => {
3044                self.eval_try_expression(body, handlers, env)
3045            }
3046            Expression::SuperCall { arguments, .. } => {
3047                let (values, named_args) = self.eval_call_arguments(arguments, Rc::clone(&env))?;
3048                if !named_args.is_empty() {
3049                    return Err(ZuzuRustError::runtime(
3050                        "named arguments are not implemented for super()",
3051                    ));
3052                }
3053                self.eval_super_call(values, env)
3054            }
3055        }
3056    }
3057
3058    fn render_template_parts(
3059        &self,
3060        parts: &[TemplatePart],
3061        env: Rc<Environment>,
3062    ) -> Result<String> {
3063        let mut out = String::new();
3064        for part in parts {
3065            match part {
3066                TemplatePart::Text { value, .. } => out.push_str(value),
3067                TemplatePart::Expression { expression, .. } => {
3068                    let value = self.eval_expression(expression, Rc::clone(&env))?;
3069                    out.push_str(&self.render_value(&value)?);
3070                }
3071            }
3072        }
3073        Ok(out)
3074    }
3075
3076    fn eval_call_arguments(
3077        &self,
3078        arguments: &[CallArgument],
3079        env: Rc<Environment>,
3080    ) -> Result<(Vec<Value>, Vec<(String, Value)>)> {
3081        let mut positional = Vec::with_capacity(arguments.len());
3082        let mut named = Vec::new();
3083        for argument in arguments {
3084            match argument {
3085                CallArgument::Positional { value, .. } => {
3086                    positional.push(self.eval_expression(value, Rc::clone(&env))?);
3087                }
3088                CallArgument::Spread { value, .. } => {
3089                    let spread_value = self.eval_expression(value, Rc::clone(&env))?;
3090                    self.expand_call_spread_argument(spread_value, &mut positional, &mut named)?;
3091                }
3092                CallArgument::Named { name, value, .. } => {
3093                    named.push((
3094                        self.eval_dict_key(name, Rc::clone(&env))?,
3095                        self.eval_expression(value, Rc::clone(&env))?,
3096                    ));
3097                }
3098            }
3099        }
3100        Ok((positional, named))
3101    }
3102
3103    fn eval_method_call_arguments(
3104        &self,
3105        arguments: &[CallArgument],
3106        env: Rc<Environment>,
3107    ) -> Result<(Vec<Value>, Vec<(String, Value)>)> {
3108        self.eval_call_arguments(arguments, env)
3109    }
3110
3111    fn expand_call_spread_argument(
3112        &self,
3113        value: Value,
3114        positional: &mut Vec<Value>,
3115        named: &mut Vec<(String, Value)>,
3116    ) -> Result<()> {
3117        let value = self.deref_value(&value)?;
3118        match value {
3119            Value::Array(values) | Value::SystemArray(values) => {
3120                positional.extend(values);
3121                Ok(())
3122            }
3123            Value::Dict(values) | Value::SystemDict(values) => {
3124                let mut keys: Vec<_> = values.keys().cloned().collect();
3125                keys.sort();
3126                for key in keys {
3127                    named.push((
3128                        key.clone(),
3129                        values.get(&key).cloned().unwrap_or(Value::Null),
3130                    ));
3131                }
3132                Ok(())
3133            }
3134            Value::PairList(values) => {
3135                named.extend(values);
3136                Ok(())
3137            }
3138            other => Err(ZuzuRustError::runtime(format!(
3139                "spread call argument expects Array, Dict, or PairList; got {}",
3140                other.type_name()
3141            ))),
3142        }
3143    }
3144
3145    fn eval_path_haystack_argument(
3146        &self,
3147        expr: &Expression,
3148        env: Rc<Environment>,
3149    ) -> Result<Value> {
3150        self.eval_expression(expr, env)
3151    }
3152
3153    fn eval_binary(
3154        &self,
3155        operator: &str,
3156        left: &Expression,
3157        right: &Expression,
3158        env: Rc<Environment>,
3159    ) -> Result<Value> {
3160        match operator {
3161            "and" | "⋀" => {
3162                let left_value = self.eval_expression(left, Rc::clone(&env))?;
3163                if !self.value_is_truthy(&left_value)? {
3164                    return Ok(Value::Boolean(false));
3165                }
3166                Ok(Value::Boolean(
3167                    self.value_is_truthy(&self.eval_expression(right, env)?)?,
3168                ))
3169            }
3170            "and?" | "⋀?" => {
3171                let left_value = self.eval_expression(left, Rc::clone(&env))?;
3172                if self.value_is_truthy(&left_value)? {
3173                    return self.eval_expression(right, env);
3174                }
3175                Ok(left_value)
3176            }
3177            "or" | "⋁" => {
3178                let left_value = self.eval_expression(left, Rc::clone(&env))?;
3179                if self.value_is_truthy(&left_value)? {
3180                    return Ok(Value::Boolean(true));
3181                }
3182                Ok(Value::Boolean(
3183                    self.value_is_truthy(&self.eval_expression(right, env)?)?,
3184                ))
3185            }
3186            "or?" | "⋁?" => {
3187                let left_value = self.eval_expression(left, Rc::clone(&env))?;
3188                if self.value_is_truthy(&left_value)? {
3189                    return Ok(left_value);
3190                }
3191                self.eval_expression(right, env)
3192            }
3193            "nor" | "⊽" => {
3194                let left_value = self.eval_expression(left, Rc::clone(&env))?;
3195                if self.value_is_truthy(&left_value)? {
3196                    return Ok(Value::Boolean(false));
3197                }
3198                Ok(Value::Boolean(
3199                    !self.value_is_truthy(&self.eval_expression(right, env)?)?,
3200                ))
3201            }
3202            "nor?" | "⊽?" => {
3203                let left_value = self.eval_expression(left, Rc::clone(&env))?;
3204                let right_value = self.eval_expression(right, env)?;
3205                if self.value_is_truthy(&left_value)? {
3206                    if self.value_is_truthy(&right_value)? {
3207                        Ok(Value::Boolean(false))
3208                    } else {
3209                        Ok(right_value)
3210                    }
3211                } else if self.value_is_truthy(&right_value)? {
3212                    Ok(left_value)
3213                } else {
3214                    Ok(Value::Boolean(true))
3215                }
3216            }
3217            "xor" | "⊻" => {
3218                let lhs = self.value_is_truthy(&self.eval_expression(left, Rc::clone(&env))?)?;
3219                let rhs = self.value_is_truthy(&self.eval_expression(right, env)?)?;
3220                Ok(Value::Boolean(lhs ^ rhs))
3221            }
3222            "xor?" | "⊻?" => {
3223                let left_value = self.eval_expression(left, Rc::clone(&env))?;
3224                let right_value = self.eval_expression(right, env)?;
3225                if self.value_is_truthy(&left_value)? {
3226                    if self.value_is_truthy(&right_value)? {
3227                        Ok(Value::Boolean(false))
3228                    } else {
3229                        Ok(left_value)
3230                    }
3231                } else if self.value_is_truthy(&right_value)? {
3232                    Ok(right_value)
3233                } else {
3234                    Ok(Value::Boolean(false))
3235                }
3236            }
3237            "xnor" | "↔" => {
3238                let lhs = self.value_is_truthy(&self.eval_expression(left, Rc::clone(&env))?)?;
3239                let rhs = self.value_is_truthy(&self.eval_expression(right, env)?)?;
3240                Ok(Value::Boolean(lhs == rhs))
3241            }
3242            "xnor?" | "↔?" => {
3243                let left_value = self.eval_expression(left, Rc::clone(&env))?;
3244                let right_value = self.eval_expression(right, env)?;
3245                if self.value_is_truthy(&left_value)? {
3246                    Ok(right_value)
3247                } else if self.value_is_truthy(&right_value)? {
3248                    Ok(left_value)
3249                } else {
3250                    Ok(Value::Boolean(true))
3251                }
3252            }
3253            "nand" | "⊼" => {
3254                let lhs = self.value_is_truthy(&self.eval_expression(left, Rc::clone(&env))?)?;
3255                let rhs = self.value_is_truthy(&self.eval_expression(right, env)?)?;
3256                Ok(Value::Boolean(!(lhs && rhs)))
3257            }
3258            "nand?" | "⊼?" => {
3259                let left_value = self.eval_expression(left, Rc::clone(&env))?;
3260                let right_value = self.eval_expression(right, env)?;
3261                if self.value_is_truthy(&left_value)? {
3262                    if self.value_is_truthy(&right_value)? {
3263                        Ok(Value::Boolean(false))
3264                    } else {
3265                        Ok(Value::Boolean(true))
3266                    }
3267                } else if self.value_is_truthy(&right_value)? {
3268                    Ok(right_value)
3269                } else {
3270                    Ok(Value::Boolean(true))
3271                }
3272            }
3273            "onlyif" | "⊨" => {
3274                let left_value = self.eval_expression(left, Rc::clone(&env))?;
3275                if !self.value_is_truthy(&left_value)? {
3276                    return Ok(Value::Boolean(true));
3277                }
3278                Ok(Value::Boolean(
3279                    self.value_is_truthy(&self.eval_expression(right, env)?)?,
3280                ))
3281            }
3282            "onlyif?" | "⊨?" => {
3283                let left_value = self.eval_expression(left, Rc::clone(&env))?;
3284                if self.value_is_truthy(&left_value)? {
3285                    return self.eval_expression(right, env);
3286                }
3287                Ok(Value::Boolean(true))
3288            }
3289            "butnot" | "⊭" => {
3290                let left_value = self.eval_expression(left, Rc::clone(&env))?;
3291                if !self.value_is_truthy(&left_value)? {
3292                    return Ok(Value::Boolean(false));
3293                }
3294                Ok(Value::Boolean(
3295                    !self.value_is_truthy(&self.eval_expression(right, env)?)?,
3296                ))
3297            }
3298            "butnot?" | "⊭?" => {
3299                let left_value = self.eval_expression(left, Rc::clone(&env))?;
3300                if !self.value_is_truthy(&left_value)? {
3301                    return Ok(left_value);
3302                }
3303                if self.value_is_truthy(&self.eval_expression(right, env)?)? {
3304                    Ok(Value::Boolean(false))
3305                } else {
3306                    Ok(left_value)
3307                }
3308            }
3309            "▷" | "|>" => {
3310                let value = self.eval_expression(left, Rc::clone(&env))?;
3311                let chain_env = Rc::new(Environment::new(Some(env)));
3312                chain_env.define("^^".to_owned(), value, false);
3313                self.eval_expression(right, chain_env)
3314            }
3315            "◁" | "<|" => {
3316                let value = self.eval_expression(right, Rc::clone(&env))?;
3317                let chain_env = Rc::new(Environment::new(Some(env)));
3318                chain_env.define("^^".to_owned(), value, false);
3319                self.eval_expression(left, chain_env)
3320            }
3321            "..." => {
3322                let start =
3323                    self.value_to_number(&self.eval_expression(left, Rc::clone(&env))?)? as i64;
3324                let end = self.value_to_number(&self.eval_expression(right, env)?)? as i64;
3325                let mut values = Vec::new();
3326                if start <= end {
3327                    for value in start..=end {
3328                        values.push(Value::Number(value as f64));
3329                    }
3330                } else {
3331                    for value in (end..=start).rev() {
3332                        values.push(Value::Number(value as f64));
3333                    }
3334                }
3335                Ok(Value::Array(values))
3336            }
3337            "default" => {
3338                let lhs = self.eval_expression(left, Rc::clone(&env))?;
3339                let rhs = self.eval_expression(right, env)?;
3340                self.eval_default_operator(lhs, rhs)
3341            }
3342            "_" => {
3343                let lhs = self.eval_expression(left, Rc::clone(&env))?;
3344                let rhs = self.eval_expression(right, env)?;
3345                self.concat_values(lhs, rhs)
3346            }
3347            "+" | "-" | "*" | "×" | "/" | "÷" | "mod" | "**" => {
3348                let lhs = self.value_to_number(&self.eval_expression(left, Rc::clone(&env))?)?;
3349                let rhs = self.value_to_number(&self.eval_expression(right, env)?)?;
3350                let value = match operator {
3351                    "+" => lhs + rhs,
3352                    "-" => lhs - rhs,
3353                    "*" | "×" => lhs * rhs,
3354                    "/" | "÷" => lhs / rhs,
3355                    "mod" => lhs % rhs,
3356                    "**" => lhs.powf(rhs),
3357                    _ => unreachable!(),
3358                };
3359                Ok(Value::Number(value))
3360            }
3361            ">" | "<" | ">=" | "≤" | "<=" | "≥" | "=" | "!=" | "≠" | "==" | "≡" | "≢" | "eq"
3362            | "ne" | "gt" | "ge" | "lt" | "le" | "eqi" | "nei" | "gti" | "gei" | "lti" | "lei" => {
3363                let lhs = self.eval_expression(left, Rc::clone(&env))?;
3364                let rhs = self.eval_expression(right, env)?;
3365                let result = match operator {
3366                    ">" => self.value_to_number(&lhs)? > self.value_to_number(&rhs)?,
3367                    "<" => self.value_to_number(&lhs)? < self.value_to_number(&rhs)?,
3368                    ">=" | "≥" => self.value_to_number(&lhs)? >= self.value_to_number(&rhs)?,
3369                    "<=" | "≤" => self.value_to_number(&lhs)? <= self.value_to_number(&rhs)?,
3370                    "=" => {
3371                        if lhs.is_numeric_comparable() && rhs.is_numeric_comparable() {
3372                            self.value_to_number(&lhs)? == self.value_to_number(&rhs)?
3373                        } else {
3374                            lhs.coerced_eq(&rhs)
3375                        }
3376                    }
3377                    "!=" | "≠" => {
3378                        if lhs.is_numeric_comparable() && rhs.is_numeric_comparable() {
3379                            self.value_to_number(&lhs)? != self.value_to_number(&rhs)?
3380                        } else {
3381                            !lhs.strict_eq(&rhs)
3382                        }
3383                    }
3384                    "==" | "≡" => lhs.strict_eq(&rhs),
3385                    "≢" => !lhs.strict_eq(&rhs),
3386                    "eq" => {
3387                        self.value_to_operator_string(&lhs)?
3388                            == self.value_to_operator_string(&rhs)?
3389                    }
3390                    "ne" => {
3391                        self.value_to_operator_string(&lhs)?
3392                            != self.value_to_operator_string(&rhs)?
3393                    }
3394                    "gt" => {
3395                        self.value_to_operator_string(&lhs)?
3396                            > self.value_to_operator_string(&rhs)?
3397                    }
3398                    "ge" => {
3399                        self.value_to_operator_string(&lhs)?
3400                            >= self.value_to_operator_string(&rhs)?
3401                    }
3402                    "lt" => {
3403                        self.value_to_operator_string(&lhs)?
3404                            < self.value_to_operator_string(&rhs)?
3405                    }
3406                    "le" => {
3407                        self.value_to_operator_string(&lhs)?
3408                            <= self.value_to_operator_string(&rhs)?
3409                    }
3410                    "eqi" => {
3411                        self.value_to_operator_string(&lhs)?.to_lowercase()
3412                            == self.value_to_operator_string(&rhs)?.to_lowercase()
3413                    }
3414                    "nei" => {
3415                        self.value_to_operator_string(&lhs)?.to_lowercase()
3416                            != self.value_to_operator_string(&rhs)?.to_lowercase()
3417                    }
3418                    "gti" => {
3419                        self.value_to_operator_string(&lhs)?.to_lowercase()
3420                            > self.value_to_operator_string(&rhs)?.to_lowercase()
3421                    }
3422                    "gei" => {
3423                        self.value_to_operator_string(&lhs)?.to_lowercase()
3424                            >= self.value_to_operator_string(&rhs)?.to_lowercase()
3425                    }
3426                    "lti" => {
3427                        self.value_to_operator_string(&lhs)?.to_lowercase()
3428                            < self.value_to_operator_string(&rhs)?.to_lowercase()
3429                    }
3430                    "lei" => {
3431                        self.value_to_operator_string(&lhs)?.to_lowercase()
3432                            <= self.value_to_operator_string(&rhs)?.to_lowercase()
3433                    }
3434                    _ => unreachable!(),
3435                };
3436                Ok(Value::Boolean(result))
3437            }
3438            "~" => {
3439                let target =
3440                    self.value_to_operator_string(&self.eval_expression(left, Rc::clone(&env))?)?;
3441                let regex = self.eval_expression(right, env)?;
3442                self.eval_regex_match(&target, &regex)
3443            }
3444            "<=>" | "≶" | "≷" => {
3445                let lhs = self.value_to_number(&self.eval_expression(left, Rc::clone(&env))?)?;
3446                let rhs = self.value_to_number(&self.eval_expression(right, env)?)?;
3447                let cmp = if lhs < rhs {
3448                    -1.0
3449                } else if lhs > rhs {
3450                    1.0
3451                } else {
3452                    0.0
3453                };
3454                Ok(Value::Number(cmp))
3455            }
3456            "cmp" | "cmpi" => {
3457                let lhs =
3458                    self.value_to_operator_string(&self.eval_expression(left, Rc::clone(&env))?)?;
3459                let rhs = self.value_to_operator_string(&self.eval_expression(right, env)?)?;
3460                let (lhs, rhs) = if operator == "cmpi" {
3461                    (lhs.to_lowercase(), rhs.to_lowercase())
3462                } else {
3463                    (lhs, rhs)
3464                };
3465                let cmp = if lhs < rhs {
3466                    -1.0
3467                } else if lhs > rhs {
3468                    1.0
3469                } else {
3470                    0.0
3471                };
3472                Ok(Value::Number(cmp))
3473            }
3474            "&" | "|" | "^" => {
3475                let lhs = self.eval_expression(left, Rc::clone(&env))?;
3476                let rhs = self.eval_expression(right, env)?;
3477                self.eval_bitwise(operator, lhs, rhs)
3478            }
3479            "<<" | "«" | ">>" | "»" => {
3480                let lhs = self.eval_expression(left, Rc::clone(&env))?;
3481                let rhs = self.eval_expression(right, env)?;
3482                self.eval_shift(operator, lhs, rhs)
3483            }
3484            "∣" | "divides" | "∤" => {
3485                let lhs = self.value_to_number(&self.eval_expression(left, Rc::clone(&env))?)?;
3486                let rhs = self.value_to_number(&self.eval_expression(right, env)?)?;
3487                // The left operand is the divisor: a ∣ b tests b mod a.
3488                let remainder = rhs % lhs;
3489                Ok(if operator == "∤" {
3490                    Value::Number(remainder)
3491                } else {
3492                    Value::Boolean(remainder == 0.0)
3493                })
3494            }
3495            "instanceof" => {
3496                let lhs = self.eval_expression(left, Rc::clone(&env))?;
3497                let rhs = self.eval_expression(right, env)?;
3498                Ok(Value::Boolean(self.value_instanceof(&lhs, &rhs)))
3499            }
3500            "does" => {
3501                let lhs = self.eval_expression(left, Rc::clone(&env))?;
3502                let rhs = self.eval_expression(right, env)?;
3503                Ok(Value::Boolean(self.value_does_trait(&lhs, &rhs)))
3504            }
3505            "can" => {
3506                let lhs = self.eval_expression(left, Rc::clone(&env))?;
3507                let member = self.member_name_operand(right, env)?;
3508                Ok(Value::Boolean(self.value_can_method(&lhs, &member)))
3509            }
3510            "@" | "@@" | "@?" => self.eval_path_operator(operator, left, right, env),
3511            "in" | "∈" | "∉" => {
3512                let needle = self.eval_expression(left, Rc::clone(&env))?;
3513                let haystack = self.eval_expression(right, env)?;
3514                let contains = match &haystack {
3515                    Value::Object(object) => {
3516                        self.object_builtin_collection_contains(object, &needle)
3517                    }
3518                    _ => collection_contains(&haystack, &needle),
3519                };
3520                if operator == "∉" {
3521                    Ok(Value::Boolean(!contains))
3522                } else {
3523                    Ok(Value::Boolean(contains))
3524                }
3525            }
3526            "union" | "⋃" => {
3527                let lhs = self.eval_expression(left, Rc::clone(&env))?;
3528                let rhs = self.eval_expression(right, env)?;
3529                collection_union(lhs, rhs)
3530            }
3531            "intersection" | "⋂" => {
3532                let lhs = self.eval_expression(left, Rc::clone(&env))?;
3533                let rhs = self.eval_expression(right, env)?;
3534                collection_intersection(lhs, rhs)
3535            }
3536            "\\" | "∖" => {
3537                let lhs = self.eval_expression(left, Rc::clone(&env))?;
3538                let rhs = self.eval_expression(right, env)?;
3539                collection_difference(lhs, rhs)
3540            }
3541            "subsetof" | "⊂" => {
3542                let lhs = self.eval_expression(left, Rc::clone(&env))?;
3543                let rhs = self.eval_expression(right, env)?;
3544                Ok(Value::Boolean(collection_subset(&lhs, &rhs)?))
3545            }
3546            "supersetof" | "⊃" => {
3547                let lhs = self.eval_expression(left, Rc::clone(&env))?;
3548                let rhs = self.eval_expression(right, env)?;
3549                Ok(Value::Boolean(collection_subset(&rhs, &lhs)?))
3550            }
3551            "equivalentof" | "⊂⊃" => {
3552                let lhs = self.eval_expression(left, Rc::clone(&env))?;
3553                let rhs = self.eval_expression(right, env)?;
3554                Ok(Value::Boolean(
3555                    collection_subset(&lhs, &rhs)? && collection_subset(&rhs, &lhs)?,
3556                ))
3557            }
3558            other => Err(ZuzuRustError::runtime(format!(
3559                "unsupported binary operator '{}'",
3560                other
3561            ))),
3562        }
3563    }
3564
3565    fn eval_default_operator(&self, lhs: Value, rhs: Value) -> Result<Value> {
3566        let lhs = self.deref_value(&lhs)?;
3567        let rhs = self.deref_value(&rhs)?;
3568        let rhs_type = rhs.type_name();
3569        match lhs {
3570            Value::Dict(mut values) | Value::SystemDict(mut values) => {
3571                match rhs {
3572                    Value::Dict(defaults) | Value::SystemDict(defaults) => {
3573                        let mut keys: Vec<_> = defaults.keys().cloned().collect();
3574                        keys.sort();
3575                        for key in keys {
3576                            if !values.contains_key(&key) {
3577                                values.insert(
3578                                    key.clone(),
3579                                    defaults.get(&key).cloned().unwrap_or(Value::Null),
3580                                );
3581                            }
3582                        }
3583                    }
3584                    Value::PairList(defaults) => {
3585                        for (key, value) in defaults {
3586                            if !values.contains_key(&key) {
3587                                values.insert(key, value);
3588                            }
3589                        }
3590                    }
3591                    _ => {
3592                        return Err(ZuzuRustError::runtime(format!(
3593                            "default operator right operand expects Dict or PairList, got {rhs_type}"
3594                        )));
3595                    }
3596                }
3597                Ok(Value::Dict(values))
3598            }
3599            Value::PairList(mut values) => {
3600                let original_keys: HashSet<_> = values.iter().map(|(key, _)| key.clone()).collect();
3601                self.append_pairlist_defaults(&mut values, &original_keys, rhs)?;
3602                Ok(Value::PairList(values))
3603            }
3604            Value::Null => {
3605                let original_keys = HashSet::new();
3606                let mut values = Vec::new();
3607                self.append_pairlist_defaults(&mut values, &original_keys, rhs)?;
3608                Ok(Value::PairList(values))
3609            }
3610            other => Err(ZuzuRustError::runtime(format!(
3611                "default operator left operand expects Dict, PairList, or Null, got {}",
3612                other.type_name()
3613            ))),
3614        }
3615    }
3616
3617    fn append_pairlist_defaults(
3618        &self,
3619        values: &mut Vec<(String, Value)>,
3620        original_keys: &HashSet<String>,
3621        defaults: Value,
3622    ) -> Result<()> {
3623        let defaults_type = defaults.type_name();
3624        match defaults {
3625            Value::Dict(defaults) | Value::SystemDict(defaults) => {
3626                let mut keys: Vec<_> = defaults.keys().cloned().collect();
3627                keys.sort();
3628                for key in keys {
3629                    if !original_keys.contains(&key) {
3630                        values.push((
3631                            key.clone(),
3632                            defaults.get(&key).cloned().unwrap_or(Value::Null),
3633                        ));
3634                    }
3635                }
3636                Ok(())
3637            }
3638            Value::PairList(defaults) => {
3639                values.extend(
3640                    defaults
3641                        .into_iter()
3642                        .filter(|(key, _)| !original_keys.contains(key)),
3643                );
3644                Ok(())
3645            }
3646            _ => Err(ZuzuRustError::runtime(format!(
3647                "default operator right operand expects Dict or PairList, got {defaults_type}"
3648            ))),
3649        }
3650    }
3651
3652    fn assign(
3653        &self,
3654        operator: &str,
3655        left: &Expression,
3656        right: Value,
3657        weak_write: bool,
3658        env: Rc<Environment>,
3659    ) -> Result<Value> {
3660        if let Expression::Binary {
3661            operator: path_operator,
3662            left: path_left,
3663            right: path_right,
3664            ..
3665        } = left
3666        {
3667            if is_path_operator(path_operator) {
3668                return self.assign_path_target(
3669                    path_operator,
3670                    path_left,
3671                    path_right,
3672                    operator,
3673                    right,
3674                    weak_write,
3675                    env,
3676                );
3677            }
3678        }
3679        match operator {
3680            ":=" => self.assign_lvalue(left, right, weak_write, env),
3681            "?:=" => {
3682                let current = self.eval_expression(left, Rc::clone(&env))?;
3683                if matches!(current, Value::Null) {
3684                    self.assign_lvalue(left, right, false, env)
3685                } else {
3686                    Ok(current)
3687                }
3688            }
3689            "+=" => {
3690                let current =
3691                    self.value_to_number(&self.eval_expression(left, Rc::clone(&env))?)?;
3692                self.assign_lvalue(
3693                    left,
3694                    Value::Number(current + self.value_to_number(&right)?),
3695                    false,
3696                    env,
3697                )
3698            }
3699            "-=" => {
3700                let current =
3701                    self.value_to_number(&self.eval_expression(left, Rc::clone(&env))?)?;
3702                self.assign_lvalue(
3703                    left,
3704                    Value::Number(current - self.value_to_number(&right)?),
3705                    false,
3706                    env,
3707                )
3708            }
3709            "*=" | "×=" => {
3710                let current =
3711                    self.value_to_number(&self.eval_expression(left, Rc::clone(&env))?)?;
3712                self.assign_lvalue(
3713                    left,
3714                    Value::Number(current * self.value_to_number(&right)?),
3715                    false,
3716                    env,
3717                )
3718            }
3719            "/=" | "÷=" => {
3720                let current =
3721                    self.value_to_number(&self.eval_expression(left, Rc::clone(&env))?)?;
3722                self.assign_lvalue(
3723                    left,
3724                    Value::Number(current / self.value_to_number(&right)?),
3725                    false,
3726                    env,
3727                )
3728            }
3729            "**=" => {
3730                let current =
3731                    self.value_to_number(&self.eval_expression(left, Rc::clone(&env))?)?;
3732                self.assign_lvalue(
3733                    left,
3734                    Value::Number(current.powf(self.value_to_number(&right)?)),
3735                    false,
3736                    env,
3737                )
3738            }
3739            "_=" => {
3740                let current =
3741                    self.value_to_operator_string(&self.eval_expression(left, Rc::clone(&env))?)?;
3742                self.assign_lvalue(
3743                    left,
3744                    Value::String(current + &self.value_to_operator_string(&right)?),
3745                    false,
3746                    env,
3747                )
3748            }
3749            other => Err(ZuzuRustError::runtime(format!(
3750                "unsupported assignment operator '{}'",
3751                other
3752            ))),
3753        }
3754    }
3755
3756    fn assign_lvalue(
3757        &self,
3758        target: &Expression,
3759        value: Value,
3760        weak_write: bool,
3761        env: Rc<Environment>,
3762    ) -> Result<Value> {
3763        match target {
3764            Expression::Binary {
3765                operator,
3766                left,
3767                right,
3768                ..
3769            } if is_path_operator(operator) => {
3770                self.assign_path_target(operator, left, right, ":=", value, weak_write, env)
3771            }
3772            Expression::Identifier {
3773                name,
3774                binding_depth,
3775                ..
3776            } => match env.get_resolved(*binding_depth, name) {
3777                Ok(Value::AliasRef(reference)) => {
3778                    let _ = self.assign_reference_with_weak_write(
3779                        reference,
3780                        value.clone(),
3781                        weak_write,
3782                    )?;
3783                    Ok(value)
3784                }
3785                Ok(Value::Ref(reference)) => {
3786                    let _ = self.assign_reference_with_weak_write(
3787                        reference,
3788                        value.clone(),
3789                        weak_write,
3790                    )?;
3791                    Ok(value)
3792                }
3793                Ok(_) => {
3794                    env.assign_resolved_with_weak_write(
3795                        *binding_depth,
3796                        name,
3797                        value.clone(),
3798                        weak_write,
3799                    )?;
3800                    Ok(value)
3801                }
3802                Err(err) => Err(err),
3803            },
3804            Expression::Index { object, index, .. } => {
3805                self.assign_index_target(object, index, value, weak_write, env)
3806            }
3807            Expression::DictAccess { object, key, .. } => {
3808                self.assign_dict_target(object, key, value, weak_write, env)
3809            }
3810            Expression::Slice {
3811                object, start, end, ..
3812            } => self.assign_slice_target(object, start.as_deref(), end.as_deref(), value, env),
3813            _ => Err(ZuzuRustError::runtime("unsupported assignment target")),
3814        }
3815    }
3816
3817    fn update_lvalue<F>(
3818        &self,
3819        target: &Expression,
3820        env: Rc<Environment>,
3821        update: F,
3822    ) -> Result<Value>
3823    where
3824        F: FnOnce(Value) -> Result<Value>,
3825    {
3826        match target {
3827            Expression::Identifier {
3828                name,
3829                binding_depth,
3830                ..
3831            } => {
3832                let current = env.get_resolved(*binding_depth, name)?;
3833                let reference = match &current {
3834                    Value::Ref(reference) | Value::AliasRef(reference) => {
3835                        Some(Rc::clone(reference))
3836                    }
3837                    _ => None,
3838                };
3839                let current_value = if let Some(reference) = &reference {
3840                    self.deref_value(&Value::AliasRef(Rc::clone(reference)))?
3841                } else {
3842                    current
3843                };
3844                let updated = update(current_value)?;
3845                if let Some(reference) = reference {
3846                    let _ = self.assign_reference(reference, updated.clone())?;
3847                } else {
3848                    env.assign_resolved(*binding_depth, name, updated.clone())?;
3849                }
3850                Ok(updated)
3851            }
3852            Expression::Index { object, index, .. } => {
3853                let current = self.eval_expression(target, Rc::clone(&env))?;
3854                let updated = update(current)?;
3855                self.assign_index_target(object, index, updated, false, env)
3856            }
3857            Expression::DictAccess { object, key, .. } => {
3858                let current = self.eval_expression(target, Rc::clone(&env))?;
3859                let current_value = self.deref_value(&current)?;
3860                let updated = update(current_value)?;
3861                self.assign_dict_target(object, key, updated, false, env)
3862            }
3863            Expression::Slice {
3864                object, start, end, ..
3865            } => {
3866                let current = self.eval_expression(target, Rc::clone(&env))?;
3867                let updated = update(current)?;
3868                self.assign_slice_target(object, start.as_deref(), end.as_deref(), updated, env)
3869            }
3870            _ => Err(ZuzuRustError::runtime("unsupported update target")),
3871        }
3872    }
3873
3874    fn eval_path_operator(
3875        &self,
3876        operator: &str,
3877        left: &Expression,
3878        right: &Expression,
3879        env: Rc<Environment>,
3880    ) -> Result<Value> {
3881        let haystack = self.eval_path_haystack_argument(left, Rc::clone(&env))?;
3882        let path = self.eval_expression(right, Rc::clone(&env))?;
3883        let mut path_object = self.resolve_path_operand(path)?;
3884        match operator {
3885            "@" => self.call_method(&mut path_object, "first", &[haystack, Value::Null]),
3886            "@@" => self.call_method(&mut path_object, "query", &[haystack]),
3887            "@?" => {
3888                let value = self.call_method(&mut path_object, "exists", &[haystack])?;
3889                Ok(Value::Boolean(value.is_truthy()))
3890            }
3891            _ => Err(ZuzuRustError::runtime(format!(
3892                "unsupported path operator '{}'",
3893                operator
3894            ))),
3895        }
3896    }
3897
3898    fn eval_path_ref(&self, argument: &Expression, env: Rc<Environment>) -> Result<Value> {
3899        let Expression::Binary {
3900            operator,
3901            left,
3902            right,
3903            ..
3904        } = argument
3905        else {
3906            return Err(ZuzuRustError::runtime("expected path expression"));
3907        };
3908        let path = self.eval_expression(right, Rc::clone(&env))?;
3909        let path_object = self.resolve_path_operand(path)?;
3910        let haystack = self.eval_path_haystack_argument(left, Rc::clone(&env))?;
3911        let mut path_object = path_object;
3912        match operator.as_str() {
3913            "@" => self.call_method(&mut path_object, "ref_first", &[haystack]),
3914            "@@" => self.call_method(&mut path_object, "ref_all", &[haystack]),
3915            "@?" => self.call_method(&mut path_object, "ref_maybe", &[haystack]),
3916            _ => Err(ZuzuRustError::runtime(format!(
3917                "unsupported path operator '{}'",
3918                operator
3919            ))),
3920        }
3921    }
3922
3923    fn eval_path_update(
3924        &self,
3925        argument: &Expression,
3926        env: Rc<Environment>,
3927        delta: f64,
3928        prefix: bool,
3929    ) -> Result<Value> {
3930        let Expression::Binary {
3931            operator,
3932            left,
3933            right,
3934            ..
3935        } = argument
3936        else {
3937            return Err(ZuzuRustError::runtime("expected path expression"));
3938        };
3939        let path = self.eval_expression(right, Rc::clone(&env))?;
3940        let path_object = self.resolve_path_operand(path)?;
3941        let haystack = self.eval_expression(left, Rc::clone(&env))?;
3942        let mut path_object = path_object;
3943        match operator.as_str() {
3944            "@" => {
3945                let current =
3946                    self.call_method(&mut path_object, "first", &[haystack.clone(), Value::Null])?;
3947                let updated = Value::Number(self.value_to_number(&current)? + delta);
3948                self.call_method(
3949                    &mut path_object,
3950                    "assign_first",
3951                    &[haystack, updated.clone(), Value::String(":=".to_owned())],
3952                )?;
3953                if prefix {
3954                    Ok(updated)
3955                } else {
3956                    Ok(current)
3957                }
3958            }
3959            "@@" => {
3960                let current = self.call_method(&mut path_object, "query", &[haystack.clone()])?;
3961                let Value::Array(values) = current.clone() else {
3962                    return Err(ZuzuRustError::runtime("@@ query did not return an Array"));
3963                };
3964                let updated_values = values
3965                    .iter()
3966                    .map(|value| Ok(Value::Number(self.value_to_number(value)? + delta)))
3967                    .collect::<Result<Vec<_>>>()?;
3968                let op = if delta >= 0.0 { "+=" } else { "-=" };
3969                self.call_method(
3970                    &mut path_object,
3971                    "assign_all",
3972                    &[
3973                        haystack,
3974                        Value::Number(delta.abs()),
3975                        Value::String(op.to_owned()),
3976                    ],
3977                )?;
3978                if prefix {
3979                    Ok(Value::Array(updated_values))
3980                } else {
3981                    Ok(Value::Array(values))
3982                }
3983            }
3984            "@?" => {
3985                let exists = self.call_method(&mut path_object, "exists", &[haystack.clone()])?;
3986                let matched = exists.is_truthy();
3987                if matched {
3988                    let op = if delta >= 0.0 { "+=" } else { "-=" };
3989                    self.call_method(
3990                        &mut path_object,
3991                        "assign_maybe",
3992                        &[
3993                            haystack,
3994                            Value::Number(delta.abs()),
3995                            Value::String(op.to_owned()),
3996                        ],
3997                    )?;
3998                }
3999                Ok(Value::Boolean(matched))
4000            }
4001            _ => Err(ZuzuRustError::runtime(format!(
4002                "unsupported path operator '{}'",
4003                operator
4004            ))),
4005        }
4006    }
4007
4008    fn assign_path_target(
4009        &self,
4010        path_operator: &str,
4011        path_left: &Expression,
4012        path_right: &Expression,
4013        assignment_operator: &str,
4014        value: Value,
4015        weak_write: bool,
4016        env: Rc<Environment>,
4017    ) -> Result<Value> {
4018        let path = self.eval_expression(path_right, Rc::clone(&env))?;
4019        let path_object = self.resolve_path_operand(path)?;
4020        let haystack = self.eval_path_haystack_argument(path_left, Rc::clone(&env))?;
4021        let mut path_object = path_object;
4022        let method = match path_operator {
4023            "@" => "assign_first",
4024            "@@" => "assign_all",
4025            "@?" => "assign_maybe",
4026            _ => {
4027                return Err(ZuzuRustError::runtime(format!(
4028                    "unsupported path operator '{}'",
4029                    path_operator
4030                )))
4031            }
4032        };
4033        self.call_method(
4034            &mut path_object,
4035            method,
4036            &[
4037                haystack,
4038                value,
4039                Value::String(assignment_operator.to_owned()),
4040                Value::Boolean(weak_write),
4041            ],
4042        )
4043    }
4044
4045    fn build_path_regex_payload(
4046        &self,
4047        replacement: &Expression,
4048        env: Rc<Environment>,
4049    ) -> Result<Value> {
4050        match replacement {
4051            Expression::Binary {
4052                operator,
4053                left,
4054                right,
4055                ..
4056            } if operator == "->" => {
4057                let regex_value = self.eval_expression(left, Rc::clone(&env))?;
4058                let (pattern, flags) = self.coerce_regex_operand(&regex_value).map_err(|_| {
4059                    ZuzuRustError::runtime("~= expects a regexp -> replacement expression")
4060                })?;
4061                let callback = FunctionValue {
4062                    name: None,
4063                    params: vec![Parameter {
4064                        line: right.line(),
4065                        source_file: right.source_file().map(str::to_owned),
4066                        declared_type: None,
4067                        name: "m".to_owned(),
4068                        optional: false,
4069                        variadic: false,
4070                        default_value: None,
4071                    }],
4072                    return_type: None,
4073                    body: Rc::new(RefCell::new(FunctionBody::Expression((**right).clone()))),
4074                    env,
4075                    is_async: false,
4076                    current_method: None,
4077                };
4078                Ok(Value::Array(vec![
4079                    Value::Regex(pattern, flags),
4080                    Value::Function(Rc::new(callback)),
4081                ]))
4082            }
4083            _ => Err(ZuzuRustError::runtime(
4084                "~= expects a regexp -> replacement expression",
4085            )),
4086        }
4087    }
4088
4089    fn resolve_path_operand(&self, path: Value) -> Result<Value> {
4090        match path {
4091            Value::Object(_) => Ok(path),
4092            Value::String(text) => {
4093                let class_value = match self.get_special_prop("paths") {
4094                    Value::Null => self
4095                        .load_module_exports("std/path/zz")?
4096                        .get("ZZPath")
4097                        .cloned()
4098                        .ok_or_else(|| {
4099                            ZuzuRustError::runtime("module 'std/path/zz' does not export 'ZZPath'")
4100                        })?,
4101                    value => value,
4102                };
4103                self.call_value(
4104                    class_value,
4105                    Vec::new(),
4106                    vec![("path".to_owned(), Value::String(text))],
4107                )
4108            }
4109            other => Err(ZuzuRustError::runtime(format!(
4110                "path operand must be String or path object, got {}",
4111                other.type_name()
4112            ))),
4113        }
4114    }
4115
4116    pub(in crate::runtime) fn task_resolved(&self, value: Value) -> Value {
4117        Value::Task(Rc::new(RefCell::new(TaskState {
4118            status: "fulfilled".to_owned(),
4119            kind: TaskKind::Resolved,
4120            outcome: Some(TaskOutcome::Fulfilled(value)),
4121        })))
4122    }
4123
4124    pub(in crate::runtime) fn task_rejected(&self, message: impl Into<String>) -> Value {
4125        Value::Task(Rc::new(RefCell::new(TaskState {
4126            status: "rejected".to_owned(),
4127            kind: TaskKind::Resolved,
4128            outcome: Some(TaskOutcome::Rejected(message.into())),
4129        })))
4130    }
4131
4132    pub(in crate::runtime) fn task_sleep(&self, seconds: f64) -> Value {
4133        let seconds = if seconds.is_finite() && seconds > 0.0 {
4134            seconds
4135        } else {
4136            0.0
4137        };
4138        Value::Task(Rc::new(RefCell::new(TaskState {
4139            status: "sleeping".to_owned(),
4140            kind: TaskKind::Sleep {
4141                deadline: Instant::now() + Duration::from_secs_f64(seconds),
4142            },
4143            outcome: None,
4144        })))
4145    }
4146
4147    pub(in crate::runtime) fn task_yield(&self) -> Value {
4148        if self.check_worker_cancelled().is_err() {
4149            return self.task_rejected("CancelledException: worker cancelled");
4150        }
4151        self.task_sleep(0.0)
4152    }
4153
4154    pub(in crate::runtime) fn task_all(&self, tasks: Vec<Value>) -> Value {
4155        let task = Rc::new(RefCell::new(TaskState {
4156            status: "waiting".to_owned(),
4157            kind: TaskKind::All { tasks },
4158            outcome: None,
4159        }));
4160        self.schedule_task_driver(Rc::clone(&task));
4161        Value::Task(task)
4162    }
4163
4164    pub(in crate::runtime) fn task_race(&self, tasks: Vec<Value>) -> Value {
4165        let task = Rc::new(RefCell::new(TaskState {
4166            status: "waiting".to_owned(),
4167            kind: TaskKind::Race { tasks },
4168            outcome: None,
4169        }));
4170        self.schedule_task_driver(Rc::clone(&task));
4171        Value::Task(task)
4172    }
4173
4174    pub(in crate::runtime) fn task_timeout(&self, seconds: f64, task: Value) -> Value {
4175        let seconds = if seconds.is_finite() && seconds > 0.0 {
4176            seconds
4177        } else {
4178            0.0
4179        };
4180        let task = Rc::new(RefCell::new(TaskState {
4181            status: "waiting".to_owned(),
4182            kind: TaskKind::Timeout {
4183                deadline: Instant::now() + Duration::from_secs_f64(seconds),
4184                seconds,
4185                task,
4186            },
4187            outcome: None,
4188        }));
4189        self.schedule_task_driver(Rc::clone(&task));
4190        Value::Task(task)
4191    }
4192
4193    pub(in crate::runtime) fn task_channel_recv(
4194        &self,
4195        channel: Rc<RefCell<ChannelState>>,
4196    ) -> Value {
4197        Value::Task(Rc::new(RefCell::new(TaskState {
4198            status: "waiting".to_owned(),
4199            kind: TaskKind::ChannelRecv { channel },
4200            outcome: None,
4201        })))
4202    }
4203
4204    pub(in crate::runtime) fn task_native_async<F>(
4205        &self,
4206        future: F,
4207        cancel_requested: Option<Rc<Cell<bool>>>,
4208    ) -> Value
4209    where
4210        F: Future<Output = Result<Value>> + 'static,
4211    {
4212        let task = Rc::new(RefCell::new(TaskState {
4213            status: "pending".to_owned(),
4214            kind: TaskKind::NativeAsync { cancel_requested },
4215            outcome: None,
4216        }));
4217        self.async_executor
4218            .spawn_local(drive_native_async_task(Rc::clone(&task), future));
4219        Value::Task(task)
4220    }
4221
4222    pub(in crate::runtime) fn register_worker_endpoint(
4223        &self,
4224        endpoint: WorkerEndpointState,
4225    ) -> usize {
4226        let id = {
4227            let mut next_id = self.next_worker_endpoint_id.borrow_mut();
4228            let id = *next_id;
4229            *next_id += 1;
4230            id
4231        };
4232        self.worker_endpoints.borrow_mut().insert(id, endpoint);
4233        id
4234    }
4235
4236    fn task_from_function(
4237        &self,
4238        function: Rc<FunctionValue>,
4239        args: Vec<Value>,
4240        named_args: Vec<(String, Value)>,
4241    ) -> Value {
4242        Value::Task(Rc::new(RefCell::new(TaskState {
4243            status: "pending".to_owned(),
4244            kind: TaskKind::Function {
4245                function,
4246                args,
4247                named_args,
4248                started: false,
4249            },
4250            outcome: None,
4251        })))
4252    }
4253
4254    pub(in crate::runtime) fn await_if_task(&self, value: Value) -> Result<Value> {
4255        match value {
4256            Value::Task(task) => self.await_task(task),
4257            other => Ok(other),
4258        }
4259    }
4260
4261    fn await_value(&self, value: Value) -> Result<Value> {
4262        match value {
4263            Value::Task(task) => self.await_task(task),
4264            other => Err(ZuzuRustError::runtime(format!(
4265                "await block must return a Task, got {}",
4266                other.type_name()
4267            ))),
4268        }
4269    }
4270
4271    fn await_task(&self, task: Rc<RefCell<TaskState>>) -> Result<Value> {
4272        loop {
4273            self.check_worker_cancelled()?;
4274            if self.poll_task(&task)? {
4275                return self.task_result(&task);
4276            }
4277            self.check_worker_cancelled()?;
4278            self.wait_for_task_progress(&task);
4279        }
4280    }
4281
4282    fn schedule_task_driver(&self, task: Rc<RefCell<TaskState>>) {
4283        let runtime = Rc::downgrade(&self.inner);
4284        self.async_executor
4285            .spawn_local(drive_scheduled_task(runtime, task));
4286    }
4287
4288    fn wait_for_task_progress(&self, task: &Rc<RefCell<TaskState>>) {
4289        if let Some(deadline) = self.next_scheduler_deadline(Some(task)) {
4290            let deadline = if self.worker_cancel_requested.is_some() {
4291                deadline.min(Instant::now() + Duration::from_millis(10))
4292            } else {
4293                deadline
4294            };
4295            self.async_executor.sleep_until(deadline);
4296        } else {
4297            self.async_executor.sleep_for(Duration::from_millis(1));
4298        }
4299    }
4300
4301    fn next_scheduler_deadline(&self, target: Option<&Rc<RefCell<TaskState>>>) -> Option<Instant> {
4302        let mut deadline = target.and_then(|task| self.next_task_deadline(task));
4303        for task in self.background_tasks.borrow().iter() {
4304            if target
4305                .map(|target| Rc::ptr_eq(target, task))
4306                .unwrap_or(false)
4307            {
4308                continue;
4309            }
4310            deadline = earliest_deadline(deadline, self.next_task_deadline(task));
4311        }
4312        deadline
4313    }
4314
4315    fn next_task_deadline(&self, task: &Rc<RefCell<TaskState>>) -> Option<Instant> {
4316        enum Children {
4317            None,
4318            One(Rc<RefCell<TaskState>>),
4319            Many(Vec<Value>),
4320        }
4321
4322        let (deadline, children) = {
4323            let state = task.borrow();
4324            match &state.kind {
4325                TaskKind::Sleep { deadline } => (Some(*deadline), Children::None),
4326                TaskKind::Timeout {
4327                    deadline,
4328                    task: inner,
4329                    ..
4330                } => (Some(*deadline), Children::Many(vec![inner.clone()])),
4331                TaskKind::FunctionWaiting { awaited, .. }
4332                | TaskKind::SpawnWaiting { awaited, .. } => {
4333                    (None, Children::One(Rc::clone(awaited)))
4334                }
4335                TaskKind::All { tasks } | TaskKind::Race { tasks } => {
4336                    (None, Children::Many(tasks.clone()))
4337                }
4338                TaskKind::Function { .. } | TaskKind::Spawn { .. } => {
4339                    (Some(Instant::now()), Children::None)
4340                }
4341                TaskKind::Resolved
4342                | TaskKind::ChannelRecv { .. }
4343                | TaskKind::NativeAsync { .. } => (None, Children::None),
4344            }
4345        };
4346
4347        match children {
4348            Children::None => deadline,
4349            Children::One(child) => earliest_deadline(deadline, self.next_task_deadline(&child)),
4350            Children::Many(values) => values.into_iter().fold(deadline, |current, value| {
4351                let Value::Task(child) = value else {
4352                    return current;
4353                };
4354                earliest_deadline(current, self.next_task_deadline(&child))
4355            }),
4356        }
4357    }
4358
4359    fn task_result(&self, task: &Rc<RefCell<TaskState>>) -> Result<Value> {
4360        match task.borrow().outcome.clone() {
4361            Some(TaskOutcome::Fulfilled(value)) => Ok(value),
4362            Some(TaskOutcome::Rejected(message)) => Err(ZuzuRustError::thrown(message)),
4363            Some(TaskOutcome::Cancelled(reason)) => Err(ZuzuRustError::thrown(format!(
4364                "CancelledException: {reason}"
4365            ))),
4366            None => Err(ZuzuRustError::runtime("task is not complete")),
4367        }
4368    }
4369
4370    fn task_outcome_value(&self, task: &Rc<RefCell<TaskState>>) -> Option<TaskOutcome> {
4371        task.borrow().outcome.clone()
4372    }
4373
4374    fn poll_task(&self, task: &Rc<RefCell<TaskState>>) -> Result<bool> {
4375        if task.borrow().outcome.is_some() {
4376            return Ok(true);
4377        }
4378
4379        let task_id = Rc::as_ptr(task) as usize;
4380        {
4381            let mut polling_tasks = self.polling_tasks.borrow_mut();
4382            if polling_tasks.contains(&task_id) {
4383                return Ok(false);
4384            }
4385            polling_tasks.push(task_id);
4386        }
4387        let _polling_guard = PollTaskGuard {
4388            stack: &self.polling_tasks,
4389            task_id,
4390        };
4391
4392        let mut complete = None;
4393        {
4394            let mut state = task.borrow_mut();
4395            match &mut state.kind {
4396                TaskKind::Resolved => {}
4397                TaskKind::Sleep { deadline } => {
4398                    if Instant::now() >= *deadline {
4399                        complete = Some(TaskOutcome::Fulfilled(Value::Null));
4400                    }
4401                }
4402                TaskKind::Function {
4403                    function,
4404                    args,
4405                    named_args,
4406                    started,
4407                } => {
4408                    *started = true;
4409                    let function = Rc::clone(function);
4410                    let args = args.clone();
4411                    let named_args = named_args.clone();
4412                    state.status = "running".to_owned();
4413                    drop(state);
4414                    let result = self.start_async_function_task(&function, args, named_args);
4415                    let mut state = task.borrow_mut();
4416                    match result {
4417                        Ok(AsyncPoll::Complete(value)) => {
4418                            complete = Some(TaskOutcome::Fulfilled(value));
4419                        }
4420                        Ok(AsyncPoll::Await {
4421                            awaited,
4422                            frames,
4423                            disposition,
4424                        }) => {
4425                            state.status = "waiting".to_owned();
4426                            state.kind = TaskKind::FunctionWaiting {
4427                                awaited,
4428                                frames,
4429                                disposition,
4430                            };
4431                            return Ok(false);
4432                        }
4433                        Err(ZuzuRustError::Thrown { value, .. }) => {
4434                            complete = Some(TaskOutcome::Rejected(value));
4435                        }
4436                        Err(err) => {
4437                            complete = Some(TaskOutcome::Rejected(err.to_string()));
4438                        }
4439                    }
4440                    state.status = "running".to_owned();
4441                }
4442                TaskKind::FunctionWaiting {
4443                    awaited,
4444                    frames,
4445                    disposition,
4446                } => {
4447                    let awaited = Rc::clone(awaited);
4448                    let frames = std::mem::take(frames);
4449                    let disposition = disposition.clone();
4450                    drop(state);
4451                    if !self.poll_task(&awaited)? {
4452                        let mut state = task.borrow_mut();
4453                        state.kind = TaskKind::FunctionWaiting {
4454                            awaited,
4455                            frames,
4456                            disposition,
4457                        };
4458                        return Ok(false);
4459                    }
4460                    match self.task_result(&awaited) {
4461                        Ok(awaited_value) => {
4462                            if matches!(disposition, AwaitDisposition::Return) {
4463                                let value = self.finish_async_frames(&frames, awaited_value);
4464                                complete = Some(match value {
4465                                    Ok(value) => TaskOutcome::Fulfilled(value),
4466                                    Err(ZuzuRustError::Thrown { value, .. }) => {
4467                                        TaskOutcome::Rejected(value)
4468                                    }
4469                                    Err(err) => TaskOutcome::Rejected(err.to_string()),
4470                                });
4471                            } else {
4472                                let result = self.poll_async_frames(frames);
4473                                let mut state = task.borrow_mut();
4474                                match result {
4475                                    Ok(AsyncPoll::Complete(value)) => {
4476                                        complete = Some(TaskOutcome::Fulfilled(value));
4477                                    }
4478                                    Ok(AsyncPoll::Await {
4479                                        awaited,
4480                                        frames,
4481                                        disposition,
4482                                    }) => {
4483                                        state.status = "waiting".to_owned();
4484                                        state.kind = TaskKind::FunctionWaiting {
4485                                            awaited,
4486                                            frames,
4487                                            disposition,
4488                                        };
4489                                        return Ok(false);
4490                                    }
4491                                    Err(ZuzuRustError::Thrown { value, .. }) => {
4492                                        complete = Some(TaskOutcome::Rejected(value));
4493                                    }
4494                                    Err(err) => {
4495                                        complete = Some(TaskOutcome::Rejected(err.to_string()));
4496                                    }
4497                                }
4498                                state.status = "running".to_owned();
4499                            }
4500                        }
4501                        Err(ZuzuRustError::Thrown { value, .. }) => {
4502                            self.cleanup_async_frames(&frames)?;
4503                            complete = Some(TaskOutcome::Rejected(value));
4504                        }
4505                        Err(err) => {
4506                            self.cleanup_async_frames(&frames)?;
4507                            complete = Some(TaskOutcome::Rejected(err.to_string()));
4508                        }
4509                    }
4510                }
4511                TaskKind::Spawn { body, env, started } => {
4512                    *started = true;
4513                    let body = body.clone();
4514                    let env = Rc::clone(env);
4515                    state.status = "running".to_owned();
4516                    drop(state);
4517                    let needs_lexical_scope = body.needs_lexical_scope;
4518                    let body_env = if needs_lexical_scope {
4519                        Rc::new(Environment::new(Some(env)))
4520                    } else {
4521                        env
4522                    };
4523                    let result = self.poll_async_frames(vec![AsyncFrame::Do {
4524                        statements: body.statements,
4525                        index: 0,
4526                        env: body_env,
4527                        cleanup_env: needs_lexical_scope,
4528                        last: Value::Null,
4529                    }]);
4530                    let mut state = task.borrow_mut();
4531                    match result {
4532                        Ok(AsyncPoll::Complete(value)) => {
4533                            complete = Some(TaskOutcome::Fulfilled(value));
4534                        }
4535                        Ok(AsyncPoll::Await {
4536                            awaited,
4537                            frames,
4538                            disposition,
4539                        }) => {
4540                            state.status = "waiting".to_owned();
4541                            state.kind = TaskKind::SpawnWaiting {
4542                                awaited,
4543                                frames,
4544                                disposition,
4545                            };
4546                            return Ok(false);
4547                        }
4548                        Err(ZuzuRustError::Thrown { value, .. }) => {
4549                            complete = Some(TaskOutcome::Rejected(value));
4550                        }
4551                        Err(err) => {
4552                            complete = Some(TaskOutcome::Rejected(err.to_string()));
4553                        }
4554                    }
4555                    state.status = "running".to_owned();
4556                }
4557                TaskKind::SpawnWaiting {
4558                    awaited,
4559                    frames,
4560                    disposition,
4561                } => {
4562                    let awaited = Rc::clone(awaited);
4563                    let mut frames = std::mem::take(frames);
4564                    let disposition = disposition.clone();
4565                    drop(state);
4566                    if !self.poll_task(&awaited)? {
4567                        let mut state = task.borrow_mut();
4568                        state.kind = TaskKind::SpawnWaiting {
4569                            awaited,
4570                            frames,
4571                            disposition,
4572                        };
4573                        return Ok(false);
4574                    }
4575                    match self.task_result(&awaited) {
4576                        Ok(awaited_value) => {
4577                            if matches!(disposition, AwaitDisposition::StoreLast) {
4578                                if let Some(frame) = frames.last_mut() {
4579                                    frame.set_last(awaited_value);
4580                                }
4581                            }
4582                            let result = self.poll_async_frames(frames);
4583                            let mut state = task.borrow_mut();
4584                            match result {
4585                                Ok(AsyncPoll::Complete(value)) => {
4586                                    complete = Some(TaskOutcome::Fulfilled(value));
4587                                }
4588                                Ok(AsyncPoll::Await {
4589                                    awaited,
4590                                    frames,
4591                                    disposition,
4592                                }) => {
4593                                    state.status = "waiting".to_owned();
4594                                    state.kind = TaskKind::SpawnWaiting {
4595                                        awaited,
4596                                        frames,
4597                                        disposition,
4598                                    };
4599                                    return Ok(false);
4600                                }
4601                                Err(ZuzuRustError::Thrown { value, .. }) => {
4602                                    complete = Some(TaskOutcome::Rejected(value));
4603                                }
4604                                Err(err) => {
4605                                    complete = Some(TaskOutcome::Rejected(err.to_string()));
4606                                }
4607                            }
4608                            state.status = "running".to_owned();
4609                        }
4610                        Err(ZuzuRustError::Thrown { value, .. }) => {
4611                            self.cleanup_async_frames(&frames)?;
4612                            complete = Some(TaskOutcome::Rejected(value));
4613                        }
4614                        Err(err) => {
4615                            self.cleanup_async_frames(&frames)?;
4616                            complete = Some(TaskOutcome::Rejected(err.to_string()));
4617                        }
4618                    }
4619                }
4620                TaskKind::All { tasks } => {
4621                    let tasks = tasks.clone();
4622                    drop(state);
4623                    let mut results = Vec::new();
4624                    let mut all_done = true;
4625                    let mut failed_child: Option<Rc<RefCell<TaskState>>> = None;
4626                    for value in &tasks {
4627                        match value {
4628                            Value::Task(child) => {
4629                                if !self.poll_task(child)? {
4630                                    all_done = false;
4631                                    results.push(Value::Null);
4632                                    continue;
4633                                }
4634                                match self.task_outcome_value(child) {
4635                                    Some(TaskOutcome::Fulfilled(value)) => results.push(value),
4636                                    Some(TaskOutcome::Rejected(message)) => {
4637                                        complete = Some(TaskOutcome::Rejected(message));
4638                                        failed_child = Some(Rc::clone(child));
4639                                        break;
4640                                    }
4641                                    Some(TaskOutcome::Cancelled(reason)) => {
4642                                        complete = Some(TaskOutcome::Cancelled(reason));
4643                                        failed_child = Some(Rc::clone(child));
4644                                        break;
4645                                    }
4646                                    None => all_done = false,
4647                                }
4648                            }
4649                            other => results.push(other.clone()),
4650                        }
4651                    }
4652                    if complete.is_some() {
4653                        for value in tasks {
4654                            if let Value::Task(child) = value {
4655                                if failed_child
4656                                    .as_ref()
4657                                    .map(|failed| Rc::ptr_eq(failed, &child))
4658                                    .unwrap_or(false)
4659                                {
4660                                    continue;
4661                                }
4662                                self.cancel_task(
4663                                    &child,
4664                                    Value::String("Task cancelled".to_owned()),
4665                                );
4666                            }
4667                        }
4668                    }
4669                    if complete.is_none() && all_done {
4670                        complete = Some(TaskOutcome::Fulfilled(Value::Array(results)));
4671                    }
4672                }
4673                TaskKind::Race { tasks } => {
4674                    let tasks = tasks.clone();
4675                    drop(state);
4676                    let mut winner: Option<Rc<RefCell<TaskState>>> = None;
4677                    for value in &tasks {
4678                        match value {
4679                            Value::Task(child) => {
4680                                if self.poll_task(&child)? {
4681                                    winner = Some(Rc::clone(&child));
4682                                    complete = self.task_outcome_value(&child);
4683                                    break;
4684                                }
4685                            }
4686                            other => {
4687                                complete = Some(TaskOutcome::Fulfilled(other.clone()));
4688                                break;
4689                            }
4690                        }
4691                    }
4692                    if complete.is_some() {
4693                        for value in tasks {
4694                            if let Value::Task(child) = value {
4695                                if winner
4696                                    .as_ref()
4697                                    .map(|winner| Rc::ptr_eq(winner, &child))
4698                                    .unwrap_or(false)
4699                                {
4700                                    continue;
4701                                }
4702                                self.cancel_task(
4703                                    &child,
4704                                    Value::String("race loser cancelled".to_owned()),
4705                                );
4706                            }
4707                        }
4708                    }
4709                }
4710                TaskKind::Timeout {
4711                    deadline,
4712                    seconds,
4713                    task: inner,
4714                } => {
4715                    let expired = Instant::now() >= *deadline;
4716                    let inner = inner.clone();
4717                    let message = format!("timeout after {seconds}s");
4718                    drop(state);
4719                    if expired {
4720                        if let Value::Task(child) = &inner {
4721                            self.cancel_task(child, Value::String(message.clone()));
4722                        }
4723                        complete = Some(TaskOutcome::Rejected(format!(
4724                            "TimeoutException: {message}"
4725                        )));
4726                    } else if let Value::Task(child) = inner {
4727                        if self.poll_task(&child)? {
4728                            complete = self.task_outcome_value(&child);
4729                        }
4730                    } else {
4731                        complete = Some(TaskOutcome::Fulfilled(inner));
4732                    }
4733                }
4734                TaskKind::ChannelRecv { channel } => {
4735                    let mut channel = channel.borrow_mut();
4736                    if !channel.messages.is_empty() {
4737                        complete = Some(TaskOutcome::Fulfilled(channel.messages.remove(0)));
4738                    } else if channel.closed {
4739                        complete = Some(TaskOutcome::Fulfilled(Value::Null));
4740                    }
4741                }
4742                TaskKind::NativeAsync { .. } => {}
4743            }
4744        }
4745
4746        if let Some(outcome) = complete {
4747            let mut state = task.borrow_mut();
4748            state.status = match &outcome {
4749                TaskOutcome::Fulfilled(_) => "fulfilled",
4750                TaskOutcome::Rejected(_) => "rejected",
4751                TaskOutcome::Cancelled(_) => "cancelled",
4752            }
4753            .to_owned();
4754            state.outcome = Some(outcome);
4755            return Ok(true);
4756        }
4757        Ok(false)
4758    }
4759
4760    fn cancel_task(&self, task: &Rc<RefCell<TaskState>>, reason: Value) {
4761        if task.borrow().outcome.is_some() {
4762            return;
4763        }
4764        let cancel_requested = {
4765            let state = task.borrow();
4766            match &state.kind {
4767                TaskKind::NativeAsync {
4768                    cancel_requested: Some(cancel_requested),
4769                } => Some(Rc::clone(cancel_requested)),
4770                _ => None,
4771            }
4772        };
4773        if let Some(cancel_requested) = cancel_requested {
4774            cancel_requested.set(true);
4775        }
4776        let children = child_tasks_of(task);
4777        let frames = async_frames_of(task);
4778        let reason = reason.render();
4779        {
4780            let mut state = task.borrow_mut();
4781            state.status = "cancelled".to_owned();
4782            state.outcome = Some(TaskOutcome::Cancelled(reason.clone()));
4783        }
4784        for child in children {
4785            self.cancel_task(&child, Value::String(reason.clone()));
4786        }
4787        if let Some(frames) = frames {
4788            let _ = self.cleanup_async_frames(&frames);
4789        }
4790    }
4791
4792    fn cancel_background_tasks(&self, reason: Value) {
4793        let tasks = self.background_tasks.borrow().clone();
4794        for task in tasks {
4795            self.cancel_task(&task, reason.clone());
4796        }
4797    }
4798
4799    fn call_value(
4800        &self,
4801        callee: Value,
4802        args: Vec<Value>,
4803        named_args: Vec<(String, Value)>,
4804    ) -> Result<Value> {
4805        match callee {
4806            value if value.is_weak_value() => {
4807                self.call_value(value.resolve_weak_value(), args, named_args)
4808            }
4809            Value::Shared(value) => self.call_value(value.borrow().clone(), args, named_args),
4810            Value::Function(function) => self.call_function(&function, args, named_args),
4811            Value::NativeFunction(name) => self.call_native_function(&name, args, named_args),
4812            Value::Method(method) => self.call_bound_method(&method, args, named_args),
4813            Value::Iterator(state) => {
4814                if !args.is_empty() || !named_args.is_empty() {
4815                    return Err(ZuzuRustError::runtime(
4816                        "iterator values do not take arguments",
4817                    ));
4818                }
4819                self.iterator_next(&state)
4820            }
4821            Value::Ref(reference) => self.call_ref(reference, args, named_args),
4822            Value::AliasRef(reference) => {
4823                let callee = self.deref_value(&Value::AliasRef(Rc::clone(&reference)))?;
4824                self.call_value(callee, args, named_args)
4825            }
4826            Value::Class(name) => self.construct_builtin_class(&name, args, named_args),
4827            Value::UserClass(class) => self.construct_user_class(class, args, named_args),
4828            _ => Err(ZuzuRustError::runtime(
4829                "attempted to call a non-function value",
4830            )),
4831        }
4832    }
4833
4834    fn call_native_function(
4835        &self,
4836        name: &str,
4837        args: Vec<Value>,
4838        named_args: Vec<(String, Value)>,
4839    ) -> Result<Value> {
4840        if matches!(name, "dump" | "safe_to_dump" | "ref_id") {
4841            return stdlib::call_native_function(self, name, args, named_args);
4842        }
4843        let args = args
4844            .into_iter()
4845            .map(|value| self.normalize_value(value))
4846            .collect::<Result<Vec<_>>>()?;
4847        let named_args = named_args
4848            .into_iter()
4849            .map(|(key, value)| {
4850                let value = self.normalize_value(value)?;
4851                Ok((key, value))
4852            })
4853            .collect::<Result<Vec<_>>>()?;
4854        stdlib::call_native_function(self, name, args, named_args)
4855    }
4856
4857    fn call_bound_method(
4858        &self,
4859        method: &Rc<MethodValue>,
4860        args: Vec<Value>,
4861        named_args: Vec<(String, Value)>,
4862    ) -> Result<Value> {
4863        let Some(receiver) = method.bound_receiver.clone() else {
4864            return Err(ZuzuRustError::runtime(
4865                "attempted to call an unbound method value",
4866            ));
4867        };
4868        let name = method.bound_name.as_deref().unwrap_or(&method.name);
4869        match receiver {
4870            Value::Object(object) => self.call_object_method(&object, name, &args, named_args),
4871            Value::UserClass(class) => {
4872                self.call_class_method(Rc::clone(&class), class, name, &args, named_args)
4873            }
4874            _ => Err(ZuzuRustError::runtime(
4875                "bound method receiver must be an Object or Class",
4876            )),
4877        }
4878    }
4879
4880    fn invoke_method_expression(
4881        &self,
4882        object: &Expression,
4883        name: &str,
4884        arguments: &[CallArgument],
4885        env: Rc<Environment>,
4886    ) -> Result<Value> {
4887        let receiver_value = self.eval_expression(object, Rc::clone(&env))?;
4888        let (args, named_args) = self.eval_method_call_arguments(arguments, Rc::clone(&env))?;
4889        if let Expression::Identifier { name: binding, .. } = object {
4890            let mut receiver = env.get(binding)?;
4891            let should_write_back = !matches!(receiver, Value::Ref(_) | Value::AliasRef(_))
4892                && is_mutating_collection_method(name)
4893                && matches!(
4894                    receiver,
4895                    Value::Array(_)
4896                        | Value::Set(_)
4897                        | Value::Bag(_)
4898                        | Value::Dict(_)
4899                        | Value::PairList(_)
4900                );
4901            let result = self.call_method_named(&mut receiver, name, &args, named_args.clone())?;
4902            if binding == "self" {
4903                if let Value::Object(object) = &receiver {
4904                    self.refresh_method_field_bindings(&env, object);
4905                }
4906            }
4907            if should_write_back {
4908                env.assign(binding, receiver)?;
4909            }
4910            return Ok(result);
4911        }
4912
4913        let mut receiver = receiver_value;
4914        self.call_method_named(&mut receiver, name, &args, named_args)
4915    }
4916
4917    fn call_method(&self, receiver: &mut Value, name: &str, args: &[Value]) -> Result<Value> {
4918        self.call_method_named(receiver, name, args, Vec::new())
4919    }
4920
4921    fn refresh_method_field_bindings(
4922        &self,
4923        env: &Rc<Environment>,
4924        object: &Rc<RefCell<ObjectValue>>,
4925    ) {
4926        let fields = object.borrow().fields.clone();
4927        for (name, value) in fields {
4928            if !self.is_ref_backed_composite(&value) {
4929                continue;
4930            }
4931            if matches!(
4932                env.get_optional(&name),
4933                Some(Value::Ref(_)) | Some(Value::AliasRef(_))
4934            ) {
4935                continue;
4936            }
4937            env.refresh_existing_binding(&name, value.into_shared_if_composite());
4938        }
4939    }
4940
4941    fn deref_alias_method_args(
4942        &self,
4943        args: &[Value],
4944        named_args: &[(String, Value)],
4945    ) -> Result<(Vec<Value>, Vec<(String, Value)>)> {
4946        let args = args
4947            .iter()
4948            .cloned()
4949            .map(|value| self.normalize_value(value))
4950            .collect::<Result<Vec<_>>>()?;
4951        let named_args = named_args
4952            .iter()
4953            .cloned()
4954            .map(|(key, value)| {
4955                let value = self.normalize_value(value)?;
4956                Ok((key, value))
4957            })
4958            .collect::<Result<Vec<_>>>()?;
4959        Ok((args, named_args))
4960    }
4961
4962    fn preserve_shared_method_args(
4963        &self,
4964        args: &[Value],
4965        named_args: &[(String, Value)],
4966    ) -> Result<(Vec<Value>, Vec<(String, Value)>)> {
4967        let args = args
4968            .iter()
4969            .cloned()
4970            .map(|value| match value {
4971                Value::AliasRef(_) => self.deref_value(&value),
4972                other => Ok(other),
4973            })
4974            .collect::<Result<Vec<_>>>()?;
4975        let named_args = named_args
4976            .iter()
4977            .cloned()
4978            .map(|(key, value)| match value {
4979                Value::AliasRef(_) => Ok((key, self.deref_value(&value)?)),
4980                other => Ok((key, other)),
4981            })
4982            .collect::<Result<Vec<_>>>()?;
4983        Ok((args, named_args))
4984    }
4985
4986    fn call_method_named(
4987        &self,
4988        receiver: &mut Value,
4989        name: &str,
4990        args: &[Value],
4991        named_args: Vec<(String, Value)>,
4992    ) -> Result<Value> {
4993        if receiver.is_weak_value() {
4994            *receiver = receiver.resolve_weak_value();
4995        }
4996        if let Value::Ref(reference) | Value::AliasRef(reference) = receiver {
4997            let mut current = self.deref_value(&Value::AliasRef(Rc::clone(reference)))?;
4998            let result = self.call_method_named(&mut current, name, args, named_args.clone())?;
4999            if is_mutating_collection_method(name) && self.is_ref_backed_composite(&current) {
5000                let _ = self.assign_reference(Rc::clone(reference), current)?;
5001            }
5002            return Ok(result);
5003        }
5004        if let Value::Shared(shared) = receiver {
5005            let mut current = shared.borrow().clone();
5006            let result = self.call_method_named(&mut current, name, args, named_args.clone())?;
5007            if is_mutating_collection_method(name) && self.is_ref_backed_composite(&current) {
5008                *shared.borrow_mut() = current;
5009            }
5010            return Ok(result);
5011        }
5012        match receiver {
5013            Value::Array(values) => {
5014                let (args, named_args) = if is_mutating_collection_method(name) {
5015                    self.preserve_shared_method_args(args, &named_args)?
5016                } else {
5017                    self.deref_alias_method_args(args, &named_args)?
5018                };
5019                reject_named_args(name, &named_args)?;
5020                self.call_array_method(values, name, &args)
5021            }
5022            Value::SystemArray(values) => {
5023                if is_mutating_collection_method(name) {
5024                    return Err(ZuzuRustError::runtime("Cannot modify __system__"));
5025                }
5026                let (args, named_args) = self.deref_alias_method_args(args, &named_args)?;
5027                reject_named_args(name, &named_args)?;
5028                let mut values = values.clone();
5029                self.call_array_method(&mut values, name, &args)
5030            }
5031            Value::Set(values) => {
5032                let (args, named_args) = if is_mutating_collection_method(name) {
5033                    self.preserve_shared_method_args(args, &named_args)?
5034                } else {
5035                    self.deref_alias_method_args(args, &named_args)?
5036                };
5037                reject_named_args(name, &named_args)?;
5038                self.call_set_method(values, name, &args)
5039            }
5040            Value::Bag(values) => {
5041                let (args, named_args) = if is_mutating_collection_method(name) {
5042                    self.preserve_shared_method_args(args, &named_args)?
5043                } else {
5044                    self.deref_alias_method_args(args, &named_args)?
5045                };
5046                reject_named_args(name, &named_args)?;
5047                self.call_bag_method(values, name, &args)
5048            }
5049            Value::Dict(values) => {
5050                let (args, named_args) = if is_mutating_collection_method(name) {
5051                    self.preserve_shared_method_args(args, &named_args)?
5052                } else {
5053                    self.deref_alias_method_args(args, &named_args)?
5054                };
5055                reject_named_args(name, &named_args)?;
5056                self.call_dict_method(values, name, &args)
5057            }
5058            Value::SystemDict(values) => {
5059                if is_mutating_collection_method(name) {
5060                    return Err(ZuzuRustError::runtime("Cannot modify __system__"));
5061                }
5062                let (args, named_args) = self.deref_alias_method_args(args, &named_args)?;
5063                reject_named_args(name, &named_args)?;
5064                let mut values = values.clone();
5065                self.call_dict_method(&mut values, name, &args)
5066            }
5067            Value::PairList(values) => {
5068                let (args, named_args) = if is_mutating_collection_method(name) {
5069                    self.preserve_shared_method_args(args, &named_args)?
5070                } else {
5071                    self.deref_alias_method_args(args, &named_args)?
5072                };
5073                reject_named_args(name, &named_args)?;
5074                self.call_pairlist_method(values, name, &args)
5075            }
5076            Value::Pair(key, value) => {
5077                let (args, named_args) = self.deref_alias_method_args(args, &named_args)?;
5078                reject_named_args(name, &named_args)?;
5079                self.call_pair_method(key, value, name, &args)
5080            }
5081            Value::Iterator(state) => {
5082                let (args, named_args) = self.deref_alias_method_args(args, &named_args)?;
5083                reject_named_args(name, &named_args)?;
5084                self.call_iterator_method(state, name, &args)
5085            }
5086            Value::Class(class_name) => {
5087                let (args, named_args) = self.deref_alias_method_args(args, &named_args)?;
5088                if let Some(result) = stdlib::call_builtin_class_method_named(
5089                    self,
5090                    class_name,
5091                    name,
5092                    &args,
5093                    &named_args,
5094                ) {
5095                    return result;
5096                }
5097                reject_named_args(name, &named_args)?;
5098                if let Some(result) =
5099                    stdlib::call_builtin_class_method(self, class_name, name, &args)
5100                {
5101                    result
5102                } else {
5103                    Err(ZuzuRustError::thrown(format!(
5104                        "unsupported method '{}' for {}",
5105                        name,
5106                        receiver.type_name()
5107                    )))
5108                }
5109            }
5110            Value::UserClass(class) => {
5111                self.call_class_method(Rc::clone(class), Rc::clone(class), name, args, named_args)
5112            }
5113            Value::Object(object) => self.call_object_method(object, name, args, named_args),
5114            Value::Task(task) => {
5115                let (args, named_args) = self.deref_alias_method_args(args, &named_args)?;
5116                reject_named_args(name, &named_args)?;
5117                self.call_task_method(task, name, &args)
5118            }
5119            Value::Channel(channel) => {
5120                let (args, named_args) = self.deref_alias_method_args(args, &named_args)?;
5121                reject_named_args(name, &named_args)?;
5122                self.call_channel_method(channel, name, &args)
5123            }
5124            Value::CancellationSource(source) => {
5125                let (args, named_args) = self.deref_alias_method_args(args, &named_args)?;
5126                reject_named_args(name, &named_args)?;
5127                self.call_cancellation_source_method(source, name, &args)
5128            }
5129            Value::CancellationToken(token) => {
5130                let (args, named_args) = self.deref_alias_method_args(args, &named_args)?;
5131                reject_named_args(name, &named_args)?;
5132                self.call_cancellation_token_method(token, name, &args)
5133            }
5134            Value::Null
5135            | Value::Boolean(_)
5136            | Value::Number(_)
5137            | Value::String(_)
5138            | Value::BinaryString(_)
5139            | Value::Regex(_, _) => {
5140                let (args, named_args) = self.deref_alias_method_args(args, &named_args)?;
5141                reject_named_args(name, &named_args)?;
5142                self.call_scalar_method(receiver, name, &args)
5143            }
5144            other => Err(ZuzuRustError::thrown(format!(
5145                "unsupported method '{}' for {}",
5146                name,
5147                other.type_name()
5148            ))),
5149        }
5150    }
5151
5152    fn call_scalar_method(&self, receiver: &Value, name: &str, args: &[Value]) -> Result<Value> {
5153        require_arity(name, args, 0)?;
5154        match name {
5155            "primitive_value" | "value" => Ok(receiver.clone()),
5156            "length" | "count" => match receiver {
5157                Value::String(text) => Ok(Value::Number(text.chars().count() as f64)),
5158                Value::BinaryString(bytes) => Ok(Value::Number(bytes.len() as f64)),
5159                Value::Null => Ok(Value::Number(0.0)),
5160                _ => Err(ZuzuRustError::thrown(format!(
5161                    "unsupported method '{}' for {}",
5162                    name,
5163                    receiver.type_name()
5164                ))),
5165            },
5166            "string_value" => {
5167                if matches!(receiver, Value::Null) {
5168                    Ok(Value::Null)
5169                } else {
5170                    Ok(Value::String(self.render_value(receiver)?))
5171                }
5172            }
5173            "number_value" => {
5174                if matches!(receiver, Value::Null) {
5175                    Ok(Value::Null)
5176                } else {
5177                    match self.value_to_number(receiver) {
5178                        Ok(number) => Ok(Value::Number(number)),
5179                        Err(_) => Ok(Value::Null),
5180                    }
5181                }
5182            }
5183            "type" => Ok(Value::String(self.typeof_name(receiver))),
5184            _ => Err(ZuzuRustError::thrown(format!(
5185                "unsupported method '{}' for {}",
5186                name,
5187                receiver.type_name()
5188            ))),
5189        }
5190    }
5191
5192    fn call_iterator_method(
5193        &self,
5194        state: &Rc<RefCell<IteratorState>>,
5195        name: &str,
5196        args: &[Value],
5197    ) -> Result<Value> {
5198        match name {
5199            "next" => {
5200                require_arity(name, args, 0)?;
5201                match self.iterator_next(state) {
5202                    Ok(value) => Ok(value),
5203                    Err(err) if err.is_iterator_exhausted() => Ok(Value::Null),
5204                    Err(err) => Err(err),
5205                }
5206            }
5207            _ => Err(ZuzuRustError::thrown(format!(
5208                "unsupported method '{}' for Iterator",
5209                name
5210            ))),
5211        }
5212    }
5213
5214    fn call_task_method(
5215        &self,
5216        task: &Rc<RefCell<TaskState>>,
5217        name: &str,
5218        args: &[Value],
5219    ) -> Result<Value> {
5220        match name {
5221            "status" => {
5222                require_arity(name, args, 0)?;
5223                let _ = self.poll_task(task)?;
5224                Ok(Value::String(task.borrow().status.clone()))
5225            }
5226            "done" | "is_done" => {
5227                require_arity(name, args, 0)?;
5228                let _ = self.poll_task(task)?;
5229                Ok(Value::Boolean(task.borrow().outcome.is_some()))
5230            }
5231            "poll" => {
5232                require_arity(name, args, 0)?;
5233                Ok(Value::Boolean(self.poll_task(task)?))
5234            }
5235            "cancel" => {
5236                if args.len() > 1 {
5237                    return Err(ZuzuRustError::runtime(
5238                        "task.cancel() expects an optional reason",
5239                    ));
5240                }
5241                self.cancel_task(
5242                    task,
5243                    args.first()
5244                        .cloned()
5245                        .unwrap_or_else(|| Value::String("Task cancelled".to_owned())),
5246                );
5247                Ok(Value::Task(Rc::clone(task)))
5248            }
5249            _ => Err(ZuzuRustError::thrown(format!(
5250                "unsupported method '{}' for Task",
5251                name
5252            ))),
5253        }
5254    }
5255
5256    fn call_channel_method(
5257        &self,
5258        channel: &Rc<RefCell<ChannelState>>,
5259        name: &str,
5260        args: &[Value],
5261    ) -> Result<Value> {
5262        match name {
5263            "send" => {
5264                require_arity(name, args, 1)?;
5265                let mut channel_ref = channel.borrow_mut();
5266                if channel_ref.closed {
5267                    return Ok(self.task_rejected("ChannelClosedException: send on closed channel"));
5268                }
5269                channel_ref.messages.push(args[0].clone());
5270                Ok(self.task_resolved(args[0].clone()))
5271            }
5272            "recv" => {
5273                require_arity(name, args, 0)?;
5274                Ok(self.task_channel_recv(Rc::clone(channel)))
5275            }
5276            "close" => {
5277                require_arity(name, args, 0)?;
5278                channel.borrow_mut().closed = true;
5279                Ok(Value::Null)
5280            }
5281            _ => Err(ZuzuRustError::thrown(format!(
5282                "unsupported method '{}' for Channel",
5283                name
5284            ))),
5285        }
5286    }
5287
5288    fn call_cancellation_source_method(
5289        &self,
5290        source: &Rc<RefCell<CancellationState>>,
5291        name: &str,
5292        args: &[Value],
5293    ) -> Result<Value> {
5294        match name {
5295            "token" => {
5296                require_arity(name, args, 0)?;
5297                Ok(Value::CancellationToken(Rc::clone(source)))
5298            }
5299            "cancel" => {
5300                if args.len() > 1 {
5301                    return Err(ZuzuRustError::runtime(
5302                        "cancel() expects an optional reason",
5303                    ));
5304                }
5305                let reason = args
5306                    .first()
5307                    .cloned()
5308                    .unwrap_or_else(|| Value::String("Task cancelled".to_owned()));
5309                let watched = {
5310                    let mut state = source.borrow_mut();
5311                    state.cancelled = true;
5312                    state.reason = reason.clone();
5313                    state.watched.clone()
5314                };
5315                for task in watched {
5316                    self.cancel_task(&task, reason.clone());
5317                }
5318                Ok(Value::Null)
5319            }
5320            "cancelled" => {
5321                require_arity(name, args, 0)?;
5322                Ok(Value::Boolean(source.borrow().cancelled))
5323            }
5324            "reason" => {
5325                require_arity(name, args, 0)?;
5326                Ok(source.borrow().reason.clone())
5327            }
5328            _ => Err(ZuzuRustError::thrown(format!(
5329                "unsupported method '{}' for CancellationSource",
5330                name
5331            ))),
5332        }
5333    }
5334
5335    fn call_cancellation_token_method(
5336        &self,
5337        token: &Rc<RefCell<CancellationState>>,
5338        name: &str,
5339        args: &[Value],
5340    ) -> Result<Value> {
5341        match name {
5342            "cancelled" => {
5343                require_arity(name, args, 0)?;
5344                Ok(Value::Boolean(token.borrow().cancelled))
5345            }
5346            "reason" => {
5347                require_arity(name, args, 0)?;
5348                Ok(token.borrow().reason.clone())
5349            }
5350            "throw_if_cancelled" => {
5351                require_arity(name, args, 0)?;
5352                let state = token.borrow();
5353                if state.cancelled {
5354                    Err(ZuzuRustError::thrown(format!(
5355                        "CancelledException: {}",
5356                        state.reason.render()
5357                    )))
5358                } else {
5359                    Ok(Value::Null)
5360                }
5361            }
5362            "watch" => {
5363                require_arity(name, args, 1)?;
5364                if let Value::Task(task) = &args[0] {
5365                    let mut state = token.borrow_mut();
5366                    if state.cancelled {
5367                        self.cancel_task(task, state.reason.clone());
5368                    } else {
5369                        state.watched.push(Rc::clone(task));
5370                    }
5371                    Ok(args[0].clone())
5372                } else {
5373                    Err(ZuzuRustError::runtime("watch() expects a Task"))
5374                }
5375            }
5376            _ => Err(ZuzuRustError::thrown(format!(
5377                "unsupported method '{}' for CancellationToken",
5378                name
5379            ))),
5380        }
5381    }
5382
5383    fn call_class_method(
5384        &self,
5385        dispatch_class: Rc<UserClassValue>,
5386        receiver_class: Rc<UserClassValue>,
5387        name: &str,
5388        args: &[Value],
5389        named_args: Vec<(String, Value)>,
5390    ) -> Result<Value> {
5391        let method = self
5392            .find_static_method(&dispatch_class, name)
5393            .ok_or_else(|| {
5394                ZuzuRustError::thrown(format!(
5395                    "unsupported static method '{}' for {}",
5396                    name, dispatch_class.name
5397                ))
5398            })?;
5399        self.invoke_class_method_with_method(receiver_class, name, &method, args, named_args)
5400    }
5401
5402    fn invoke_class_method_with_method(
5403        &self,
5404        receiver_class: Rc<UserClassValue>,
5405        name: &str,
5406        method: &Rc<MethodValue>,
5407        args: &[Value],
5408        named_args: Vec<(String, Value)>,
5409    ) -> Result<Value> {
5410        let field_env = Rc::new(Environment::new(Some(Rc::clone(&method.env))));
5411        field_env.define(
5412            "self".to_owned(),
5413            Value::UserClass(Rc::clone(&receiver_class)),
5414            false,
5415        );
5416        field_env.define(
5417            "this".to_owned(),
5418            Value::UserClass(Rc::clone(&receiver_class)),
5419            false,
5420        );
5421        field_env.define(
5422            "__current_class__".to_owned(),
5423            Value::UserClass(Rc::clone(&receiver_class)),
5424            false,
5425        );
5426        field_env.define(
5427            "__method_name__".to_owned(),
5428            Value::String(name.to_owned()),
5429            false,
5430        );
5431        field_env.define(
5432            "__is_static_method__".to_owned(),
5433            Value::Boolean(true),
5434            false,
5435        );
5436
5437        let function = FunctionValue {
5438            name: Some(method.name.clone()),
5439            params: method.params.clone(),
5440            return_type: method.return_type.clone(),
5441            body: Rc::new(RefCell::new(self.function_body_for_method(method))),
5442            env: field_env,
5443            is_async: method.is_async,
5444            current_method: Some(Rc::clone(&method)),
5445        };
5446        self.call_function(&function, args.to_vec(), named_args)
5447    }
5448
5449    fn eval_super_call(&self, args: Vec<Value>, env: Rc<Environment>) -> Result<Value> {
5450        let _current_class = match env.get("__current_class__")? {
5451            Value::UserClass(class) => class,
5452            _ => {
5453                return Err(ZuzuRustError::runtime(
5454                    "super() is only valid inside methods",
5455                ))
5456            }
5457        };
5458        let method_name = match env.get("__method_name__")? {
5459            Value::String(name) => name,
5460            _ => {
5461                return Err(ZuzuRustError::runtime(
5462                    "super() is only valid inside methods",
5463                ))
5464            }
5465        };
5466        let is_static = matches!(env.get("__is_static_method__")?, Value::Boolean(true));
5467
5468        if is_static {
5469            let receiver_class = match env.get("self")? {
5470                Value::UserClass(class) => class,
5471                _ => {
5472                    return Err(ZuzuRustError::runtime(
5473                        "static super() requires class receiver",
5474                    ))
5475                }
5476            };
5477            let method = self
5478                .find_next_method(&receiver_class, &method_name, true)
5479                .ok_or_else(|| {
5480                    ZuzuRustError::runtime("super() has no static parent method to call")
5481                })?;
5482            return self.invoke_class_method_with_method(
5483                Rc::clone(&receiver_class),
5484                &method_name,
5485                &method,
5486                &args,
5487                Vec::new(),
5488            );
5489        }
5490
5491        let self_object = match env.get("self")? {
5492            Value::Object(object) => object,
5493            _ => return Err(ZuzuRustError::runtime("super() requires object receiver")),
5494        };
5495        let method = self
5496            .find_next_method(&self_object.borrow().class, &method_name, false)
5497            .ok_or_else(|| {
5498                ZuzuRustError::runtime(format!(
5499                    "super() has no parent method '{}' to call",
5500                    method_name
5501                ))
5502            })?;
5503        let object_class = self_object.borrow().class.clone();
5504        self.invoke_object_method_with_context(
5505            &self_object,
5506            object_class,
5507            &method_name,
5508            &method,
5509            &args,
5510            Vec::new(),
5511        )
5512    }
5513
5514    fn invoke_object_method_with_context(
5515        &self,
5516        object: &Rc<RefCell<ObjectValue>>,
5517        current_class: Rc<UserClassValue>,
5518        invoked_name: &str,
5519        method: &Rc<MethodValue>,
5520        args: &[Value],
5521        named_args: Vec<(String, Value)>,
5522    ) -> Result<Value> {
5523        let field_env = Rc::new(Environment::new(Some(Rc::clone(&method.env))));
5524        field_env.define("self".to_owned(), Value::Object(Rc::clone(object)), false);
5525        field_env.define("this".to_owned(), Value::Object(Rc::clone(object)), false);
5526        field_env.define(
5527            "__current_class__".to_owned(),
5528            Value::UserClass(Rc::clone(&current_class)),
5529            false,
5530        );
5531        field_env.define(
5532            "__method_name__".to_owned(),
5533            Value::String(invoked_name.to_owned()),
5534            false,
5535        );
5536        field_env.define(
5537            "__is_static_method__".to_owned(),
5538            Value::Boolean(false),
5539            false,
5540        );
5541        let fields = self.collect_field_specs(&current_class);
5542        let mut original_values = HashMap::new();
5543        for field in &fields {
5544            let value = {
5545                let mut object_mut = object.borrow_mut();
5546                let value = object_mut
5547                    .fields
5548                    .get(&field.name)
5549                    .cloned()
5550                    .unwrap_or(Value::Null);
5551                if self.is_ref_backed_composite(&value) && !matches!(value, Value::Shared(_)) {
5552                    let shared = value.into_shared_if_composite();
5553                    object_mut.fields.insert(field.name.clone(), shared.clone());
5554                    shared
5555                } else {
5556                    value
5557                }
5558            };
5559            original_values.insert(field.name.clone(), value.clone());
5560            if field.mutable {
5561                field_env.define(
5562                    field.name.clone(),
5563                    Value::AliasRef(Rc::new(LvalueRef::ObjectField {
5564                        object: Rc::downgrade(object),
5565                        name: field.name.clone(),
5566                    })),
5567                    false,
5568                );
5569            } else {
5570                field_env.define(field.name.clone(), value, false);
5571            }
5572        }
5573
5574        if let Some(result) = self.maybe_return_trivial_field_getter(object, method) {
5575            return result;
5576        }
5577
5578        let function = FunctionValue {
5579            name: Some(method.name.clone()),
5580            params: method.params.clone(),
5581            return_type: method.return_type.clone(),
5582            body: Rc::new(RefCell::new(self.function_body_for_method(method))),
5583            env: Rc::clone(&field_env),
5584            is_async: method.is_async,
5585            current_method: Some(Rc::clone(method)),
5586        };
5587        let result = self.call_function(&function, args.to_vec(), named_args)?;
5588
5589        let mut object_mut = object.borrow_mut();
5590        for field in &fields {
5591            if field.mutable {
5592                continue;
5593            }
5594            if let Ok(value) = field_env.get(&field.name) {
5595                let current_object_value = object_mut
5596                    .fields
5597                    .get(&field.name)
5598                    .cloned()
5599                    .unwrap_or(Value::Null);
5600                let original_value = original_values
5601                    .get(&field.name)
5602                    .cloned()
5603                    .unwrap_or(Value::Null);
5604                if !current_object_value.coerced_eq(&original_value)
5605                    && value.coerced_eq(&original_value)
5606                {
5607                    continue;
5608                }
5609                object_mut.fields.insert(field.name.clone(), value);
5610            }
5611        }
5612        Ok(result)
5613    }
5614
5615    fn call_function(
5616        &self,
5617        function: &FunctionValue,
5618        args: Vec<Value>,
5619        named_args: Vec<(String, Value)>,
5620    ) -> Result<Value> {
5621        let forwarded = {
5622            let body = function.body.borrow();
5623            match &*body {
5624                FunctionBody::Forward(target) => Some(Rc::clone(target)),
5625                _ => None,
5626            }
5627        };
5628        if let Some(target) = forwarded {
5629            return self.call_function(&target, args, named_args);
5630        }
5631        let function_id = function as *const FunctionValue as usize;
5632        if function.is_async && !self.running_async_functions.borrow().contains(&function_id) {
5633            return Ok(self.task_from_function(Rc::new(function.clone()), args, named_args));
5634        }
5635        self.call_function_body(function, args, named_args)
5636    }
5637
5638    fn run_async_function_body(
5639        &self,
5640        function: &FunctionValue,
5641        args: Vec<Value>,
5642        named_args: Vec<(String, Value)>,
5643    ) -> Result<Value> {
5644        let function_id = function as *const FunctionValue as usize;
5645        self.running_async_functions.borrow_mut().push(function_id);
5646        let result = self.call_function_body(function, args, named_args);
5647        self.running_async_functions.borrow_mut().pop();
5648        result
5649    }
5650
5651    fn start_async_function_task(
5652        &self,
5653        function: &FunctionValue,
5654        args: Vec<Value>,
5655        named_args: Vec<(String, Value)>,
5656    ) -> Result<AsyncPoll> {
5657        let body = match &*function.body.borrow() {
5658            FunctionBody::Block(body) => body.clone(),
5659            FunctionBody::Forward(target) => {
5660                return self
5661                    .run_async_function_body(target, args, named_args)
5662                    .map(AsyncPoll::Complete);
5663            }
5664            FunctionBody::Expression(_) => {
5665                return self
5666                    .run_async_function_body(function, args, named_args)
5667                    .map(AsyncPoll::Complete);
5668            }
5669            FunctionBody::Bodyless => {
5670                return Err(ZuzuRustError::runtime(format!(
5671                    "Function '{}' has no body",
5672                    function.name.as_deref().unwrap_or("<anon>")
5673                )));
5674            }
5675        };
5676
5677        let call_env = Rc::new(Environment::new(Some(Rc::clone(&function.env))));
5678        let argc = args.len();
5679        self.bind_function_params(function, &call_env, args, named_args)?;
5680        call_env.define("__argc__".to_owned(), Value::Number(argc as f64), false);
5681
5682        self.poll_async_frames(vec![AsyncFrame::Function {
5683            statements: body.statements,
5684            index: 0,
5685            env: call_env,
5686            return_type: function.return_type.clone(),
5687            name: function.name.clone(),
5688        }])
5689    }
5690
5691    fn poll_async_frames(&self, mut frames: Vec<AsyncFrame>) -> Result<AsyncPoll> {
5692        loop {
5693            let Some(frame) = frames.last_mut() else {
5694                return Ok(AsyncPoll::Complete(Value::Null));
5695            };
5696
5697            if frame.is_complete() {
5698                let frame = frames.pop().expect("checked frame presence");
5699                let do_value = match &frame {
5700                    AsyncFrame::Do { last, .. } => Some(last.clone()),
5701                    _ => None,
5702                };
5703                self.cleanup_async_frame(&frame)?;
5704                if matches!(frame, AsyncFrame::Function { .. }) {
5705                    return Ok(AsyncPoll::Complete(Value::Null));
5706                }
5707                if let Some(value) = do_value {
5708                    if let Some(parent) = frames.last_mut() {
5709                        parent.set_last(value);
5710                        continue;
5711                    }
5712                    return Ok(AsyncPoll::Complete(value));
5713                }
5714                continue;
5715            }
5716
5717            let is_function_frame = matches!(frame, AsyncFrame::Function { .. });
5718            let is_do_frame = matches!(frame, AsyncFrame::Do { .. });
5719            let is_last = frame.index() + 1 == frame.statement_count();
5720            let env = frame.env();
5721            let statement = frame.current_statement().clone();
5722
5723            match statement {
5724                Statement::ExpressionStatement(node) => {
5725                    if let Expression::AwaitExpression { body, .. } = node.expression {
5726                        frame.advance();
5727                        let awaited = self.eval_do_expression(&body, env)?;
5728                        let Value::Task(awaited) = awaited else {
5729                            return Err(ZuzuRustError::runtime(format!(
5730                                "await block must return a Task, got {}",
5731                                awaited.type_name()
5732                            )));
5733                        };
5734                        let disposition = if is_function_frame && is_last {
5735                            AwaitDisposition::Return
5736                        } else if is_do_frame {
5737                            AwaitDisposition::StoreLast
5738                        } else {
5739                            AwaitDisposition::Discard
5740                        };
5741                        return Ok(AsyncPoll::Await {
5742                            awaited,
5743                            frames,
5744                            disposition,
5745                        });
5746                    }
5747                    if is_function_frame && is_last {
5748                        let value = self.eval_expression(&node.expression, env)?;
5749                        let value = self.finish_async_frames(&frames, value)?;
5750                        return Ok(AsyncPoll::Complete(value));
5751                    }
5752                    let value = self.eval_expression(&node.expression, env)?;
5753                    if is_do_frame {
5754                        frame.set_last(value);
5755                    }
5756                    frame.advance();
5757                }
5758                Statement::ReturnStatement(node) => {
5759                    if let Some(Expression::AwaitExpression { body, .. }) = &node.argument {
5760                        frame.advance();
5761                        let awaited = self.eval_do_expression(&body, env)?;
5762                        let Value::Task(awaited) = awaited else {
5763                            return Err(ZuzuRustError::runtime(format!(
5764                                "await block must return a Task, got {}",
5765                                awaited.type_name()
5766                            )));
5767                        };
5768                        return Ok(AsyncPoll::Await {
5769                            awaited,
5770                            frames,
5771                            disposition: AwaitDisposition::Return,
5772                        });
5773                    }
5774                    let value = self.eval_optional_expr(node.argument.as_ref(), env)?;
5775                    let value = self.finish_async_frames(&frames, value)?;
5776                    return Ok(AsyncPoll::Complete(value));
5777                }
5778                Statement::Block(block) => {
5779                    frame.advance();
5780                    let block_env = if block.needs_lexical_scope {
5781                        Rc::new(Environment::new(Some(env)))
5782                    } else {
5783                        env
5784                    };
5785                    if is_do_frame {
5786                        frames.push(AsyncFrame::Do {
5787                            statements: block.statements,
5788                            index: 0,
5789                            env: block_env,
5790                            cleanup_env: block.needs_lexical_scope,
5791                            last: Value::Null,
5792                        });
5793                    } else {
5794                        frames.push(AsyncFrame::Block {
5795                            statements: block.statements,
5796                            index: 0,
5797                            env: block_env,
5798                            cleanup_env: block.needs_lexical_scope,
5799                        });
5800                    }
5801                }
5802                other => {
5803                    if is_do_frame {
5804                        if let Some(value) =
5805                            self.eval_statement_value_in_do(&other, Rc::clone(&env))?
5806                        {
5807                            frame.set_last(value);
5808                        }
5809                        frame.advance();
5810                        let do_return = self.get_special_prop("__do_return__");
5811                        if !matches!(do_return, Value::Null) {
5812                            self.set_special_prop("__do_return__", Value::Null);
5813                            let value = self.finish_async_frames(&frames, do_return)?;
5814                            return Ok(AsyncPoll::Complete(value));
5815                        }
5816                        continue;
5817                    }
5818                    let flow = self.eval_statement(&other, Rc::clone(&env))?;
5819                    frame.advance();
5820                    match flow {
5821                        ControlFlow::Normal => {
5822                            let do_return = self.get_special_prop("__do_return__");
5823                            if !matches!(do_return, Value::Null) {
5824                                self.set_special_prop("__do_return__", Value::Null);
5825                                let value = self.finish_async_frames(&frames, do_return)?;
5826                                return Ok(AsyncPoll::Complete(value));
5827                            }
5828                        }
5829                        ControlFlow::Return(value) => {
5830                            let value = self.finish_async_frames(&frames, value)?;
5831                            return Ok(AsyncPoll::Complete(value));
5832                        }
5833                        ControlFlow::Throw(value) => match &value {
5834                            Value::String(text) => return Err(ZuzuRustError::thrown(text.clone())),
5835                            _ => {
5836                                return Err(ZuzuRustError::thrown_with_token(
5837                                    self.render_value(&value)?,
5838                                    self.store_thrown_value(value)?,
5839                                ))
5840                            }
5841                        },
5842                        ControlFlow::Continue | ControlFlow::Break => {
5843                            return Err(ZuzuRustError::runtime(
5844                                "loop control escaped function body",
5845                            ))
5846                        }
5847                    }
5848                }
5849            }
5850        }
5851    }
5852
5853    fn finish_async_frames(&self, frames: &[AsyncFrame], value: Value) -> Result<Value> {
5854        self.cleanup_async_frames_preserving(frames, &[&value])?;
5855        if let Some((return_type, name)) = frames.iter().find_map(|frame| match frame {
5856            AsyncFrame::Function {
5857                return_type, name, ..
5858            } => Some((return_type.as_deref(), name.as_deref())),
5859            AsyncFrame::Block { .. } | AsyncFrame::Do { .. } => None,
5860        }) {
5861            self.assert_return_type(return_type, name, &value)?;
5862        }
5863        Ok(value)
5864    }
5865
5866    fn cleanup_async_frames(&self, frames: &[AsyncFrame]) -> Result<()> {
5867        for frame in frames.iter().rev() {
5868            self.cleanup_async_frame(frame)?;
5869        }
5870        Ok(())
5871    }
5872
5873    fn cleanup_async_frames_preserving(
5874        &self,
5875        frames: &[AsyncFrame],
5876        preserved: &[&Value],
5877    ) -> Result<()> {
5878        for frame in frames.iter().rev() {
5879            self.cleanup_async_frame_preserving(frame, preserved)?;
5880        }
5881        Ok(())
5882    }
5883
5884    fn cleanup_async_frame(&self, frame: &AsyncFrame) -> Result<()> {
5885        self.cleanup_async_frame_preserving(frame, &[])
5886    }
5887
5888    fn cleanup_async_frame_preserving(
5889        &self,
5890        frame: &AsyncFrame,
5891        preserved: &[&Value],
5892    ) -> Result<()> {
5893        match frame {
5894            AsyncFrame::Function { env, .. } => self.cleanup_scope_preserving(env, preserved),
5895            AsyncFrame::Block {
5896                env, cleanup_env, ..
5897            }
5898            | AsyncFrame::Do {
5899                env, cleanup_env, ..
5900            } => {
5901                if *cleanup_env {
5902                    self.cleanup_scope_preserving(env, preserved)?;
5903                }
5904                Ok(())
5905            }
5906        }
5907    }
5908
5909    fn call_function_body(
5910        &self,
5911        function: &FunctionValue,
5912        args: Vec<Value>,
5913        named_args: Vec<(String, Value)>,
5914    ) -> Result<Value> {
5915        let forwarded = {
5916            let body = function.body.borrow();
5917            match &*body {
5918                FunctionBody::Forward(target) => Some(Rc::clone(target)),
5919                _ => None,
5920            }
5921        };
5922        if let Some(target) = forwarded {
5923            return self.call_function(&target, args, named_args);
5924        }
5925        let call_env = Rc::new(Environment::new(Some(Rc::clone(&function.env))));
5926        self.push_special_props_scope();
5927        if let Some(method) = &function.current_method {
5928            self.current_method_stack
5929                .borrow_mut()
5930                .push(Rc::clone(method));
5931        }
5932        let result = (|| -> Result<Value> {
5933            let argc = args.len();
5934            self.bind_function_params(function, &call_env, args, named_args)?;
5935            call_env.define("__argc__".to_owned(), Value::Number(argc as f64), false);
5936
5937            let body = function.body.borrow().clone();
5938            let flow = match body {
5939                FunctionBody::Bodyless => {
5940                    return Err(ZuzuRustError::runtime(format!(
5941                        "Function '{}' has no body",
5942                        function.name.as_deref().unwrap_or("<anon>")
5943                    )));
5944                }
5945                FunctionBody::Forward(_) => unreachable!(),
5946                FunctionBody::Block(body) => {
5947                    self.eval_function_statements(&body.statements, Rc::clone(&call_env))?
5948                }
5949                FunctionBody::Expression(expr) => {
5950                    ControlFlow::Return(self.eval_expression(&expr, Rc::clone(&call_env))?)
5951                }
5952            };
5953            match &flow {
5954                ControlFlow::Return(value) | ControlFlow::Throw(value) => {
5955                    self.cleanup_scope_preserving(&call_env, &[value])?;
5956                }
5957                _ => self.cleanup_scope(&call_env)?,
5958            }
5959            let value = match flow {
5960                ControlFlow::Normal => Ok(Value::Null),
5961                ControlFlow::Return(value) => Ok(value),
5962                ControlFlow::Throw(value) => match &value {
5963                    Value::String(text) => Err(ZuzuRustError::thrown(text.clone())),
5964                    _ => Err(ZuzuRustError::thrown_with_token(
5965                        self.render_value(&value)?,
5966                        self.store_thrown_value(value)?,
5967                    )),
5968                },
5969                ControlFlow::Continue | ControlFlow::Break => {
5970                    Err(ZuzuRustError::runtime("loop control escaped function body"))
5971                }
5972            }?;
5973            self.assert_return_type(
5974                function.return_type.as_deref(),
5975                function.name.as_deref(),
5976                &value,
5977            )?;
5978            Ok(value)
5979        })();
5980        if function.current_method.is_some() {
5981            self.current_method_stack.borrow_mut().pop();
5982        }
5983        self.pop_special_props_scope();
5984        result
5985    }
5986
5987    fn eval_dict_key(&self, key: &DictKey, env: Rc<Environment>) -> Result<String> {
5988        match key {
5989            DictKey::Identifier { name, .. } => Ok(name.clone()),
5990            DictKey::StringLiteral { value, .. } => Ok(value.clone()),
5991            DictKey::Expression { expression, .. } => {
5992                Ok(self.render_value(&self.eval_expression(expression, env)?)?)
5993            }
5994        }
5995    }
5996
5997    fn eval_index(&self, object: Value, index: Value) -> Result<Value> {
5998        let object = self.deref_value(&object)?;
5999        let index = self.value_to_number(&index)? as isize;
6000        match object {
6001            Value::Array(values) | Value::SystemArray(values) => {
6002                Ok(resolve_index(values.len(), index)
6003                    .and_then(|resolved| values.get(resolved).cloned())
6004                    .unwrap_or(Value::Null))
6005            }
6006            Value::Set(values) => Ok(resolve_index(values.len(), index)
6007                .and_then(|resolved| values.get(resolved).cloned())
6008                .unwrap_or(Value::Null)),
6009            Value::Bag(values) => Ok(resolve_index(values.len(), index)
6010                .and_then(|resolved| values.get(resolved).cloned())
6011                .unwrap_or(Value::Null)),
6012            Value::PairList(values) => Ok(resolve_index(values.len(), index)
6013                .and_then(|resolved| values.get(resolved))
6014                .map(|(key, value)| Value::Pair(key.clone(), Box::new(value.clone())))
6015                .unwrap_or(Value::Null)),
6016            Value::String(text) => Ok(resolve_index(text.chars().count(), index)
6017                .and_then(|resolved| text.chars().nth(resolved))
6018                .map(|ch| Value::String(ch.to_string()))
6019                .unwrap_or(Value::Null)),
6020            Value::BinaryString(bytes) => Ok(resolve_index(bytes.len(), index)
6021                .and_then(|resolved| bytes.get(resolved).copied())
6022                .map(|byte| Value::BinaryString(vec![byte]))
6023                .unwrap_or(Value::Null)),
6024            _ => Err(ZuzuRustError::runtime(
6025                "index access requires an indexable value",
6026            )),
6027        }
6028    }
6029
6030    fn eval_slice(&self, object: Value, start: Value, end: Value) -> Result<Value> {
6031        let object = self.deref_value(&object)?;
6032        match object {
6033            Value::Array(values) | Value::SystemArray(values) => {
6034                let len = values.len() as isize;
6035                let mut start_index = match start {
6036                    Value::Null => 0,
6037                    other => self.value_to_number(&other)? as isize,
6038                };
6039                if start_index < 0 {
6040                    start_index += len;
6041                }
6042                start_index = start_index.clamp(0, len);
6043
6044                let end_index = match end {
6045                    Value::Null => len,
6046                    other => {
6047                        let raw_end = self.value_to_number(&other)? as isize;
6048                        if raw_end < 0 {
6049                            (len + raw_end).clamp(0, len)
6050                        } else {
6051                            (start_index + raw_end).clamp(0, len)
6052                        }
6053                    }
6054                };
6055                let from = start_index.min(end_index) as usize;
6056                let to = end_index.max(start_index) as usize;
6057                Ok(Value::Array(values[from..to].to_vec()))
6058            }
6059            Value::String(text) => {
6060                let chars = text.chars().collect::<Vec<_>>();
6061                let len = chars.len() as isize;
6062                let mut start_index = match start {
6063                    Value::Null => 0,
6064                    other => self.value_to_number(&other)? as isize,
6065                };
6066                if start_index < 0 {
6067                    start_index += len;
6068                }
6069                start_index = start_index.clamp(0, len);
6070
6071                let end_index = match end {
6072                    Value::Null => len,
6073                    other => {
6074                        let raw_end = self.value_to_number(&other)? as isize;
6075                        if raw_end < 0 {
6076                            (len + raw_end).clamp(0, len)
6077                        } else {
6078                            (start_index + raw_end).clamp(0, len)
6079                        }
6080                    }
6081                };
6082                let from = start_index.min(end_index) as usize;
6083                let to = end_index.max(start_index) as usize;
6084                Ok(Value::String(chars[from..to].iter().collect()))
6085            }
6086            Value::BinaryString(bytes) => {
6087                let len = bytes.len() as isize;
6088                let mut start_index = match start {
6089                    Value::Null => 0,
6090                    other => self.value_to_number(&other)? as isize,
6091                };
6092                if start_index < 0 {
6093                    start_index += len;
6094                }
6095                start_index = start_index.clamp(0, len);
6096
6097                let end_index = match end {
6098                    Value::Null => len,
6099                    other => {
6100                        let raw_end = self.value_to_number(&other)? as isize;
6101                        if raw_end < 0 {
6102                            (len + raw_end).clamp(0, len)
6103                        } else {
6104                            (start_index + raw_end).clamp(0, len)
6105                        }
6106                    }
6107                };
6108                let from = start_index.min(end_index) as usize;
6109                let to = end_index.max(start_index) as usize;
6110                Ok(Value::BinaryString(bytes[from..to].to_vec()))
6111            }
6112            _ => Err(ZuzuRustError::runtime(
6113                "slice access requires an Array, String, or BinaryString value",
6114            )),
6115        }
6116    }
6117
6118    fn iterable_items(&self, iterable: Value) -> Result<Vec<Value>> {
6119        let iterable = self.deref_value(&iterable)?;
6120        match iterable {
6121            Value::Array(items)
6122            | Value::SystemArray(items)
6123            | Value::Set(items)
6124            | Value::Bag(items) => Ok(items),
6125            Value::Dict(map) | Value::SystemDict(map) => {
6126                let mut keys: Vec<_> = map.keys().cloned().collect();
6127                keys.sort();
6128                Ok(keys.into_iter().map(Value::String).collect())
6129            }
6130            Value::PairList(values) => Ok(values
6131                .into_iter()
6132                .map(|(key, _)| Value::String(key))
6133                .collect()),
6134            Value::String(text) => Ok(text
6135                .chars()
6136                .map(|ch| Value::String(ch.to_string()))
6137                .collect()),
6138            Value::BinaryString(bytes) => Ok(bytes
6139                .into_iter()
6140                .map(|byte| Value::BinaryString(vec![byte]))
6141                .collect()),
6142            Value::Null => Ok(Vec::new()),
6143            Value::Function(function) => {
6144                let mut items = Vec::new();
6145                loop {
6146                    match self.call_function(&function, Vec::new(), Vec::new()) {
6147                        Ok(value) => items.push(value),
6148                        Err(ZuzuRustError::Thrown { value, .. })
6149                            if value == "ExhaustedException"
6150                                || value.starts_with("ExhaustedException:") =>
6151                        {
6152                            break;
6153                        }
6154                        Err(err) => return Err(err),
6155                    }
6156                }
6157                Ok(items)
6158            }
6159            Value::Object(object) => {
6160                if self.object_has_method(&object, "to_Iterator") {
6161                    return self.iterable_items(self.call_object_method(
6162                        &object,
6163                        "to_Iterator",
6164                        &[],
6165                        Vec::new(),
6166                    )?);
6167                }
6168                if self.object_has_method(&object, "to_Array") {
6169                    return self.iterable_items(self.call_object_method(
6170                        &object,
6171                        "to_Array",
6172                        &[],
6173                        Vec::new(),
6174                    )?);
6175                }
6176                Err(ZuzuRustError::runtime(format!(
6177                    "for loop iterable is not supported yet: {}",
6178                    self.typeof_name(&Value::Object(Rc::clone(&object)))
6179                )))
6180            }
6181            Value::Iterator(state) => {
6182                let mut items = Vec::new();
6183                loop {
6184                    match self.iterator_next(&state) {
6185                        Ok(value) => items.push(value),
6186                        Err(err) if err.is_iterator_exhausted() => break,
6187                        Err(err) => return Err(err),
6188                    }
6189                }
6190                Ok(items)
6191            }
6192            other => Err(ZuzuRustError::runtime(format!(
6193                "for loop iterable is not supported yet: {}",
6194                other.type_name()
6195            ))),
6196        }
6197    }
6198
6199    fn iterator_next(&self, state: &Rc<RefCell<IteratorState>>) -> Result<Value> {
6200        let mut state = state.borrow_mut();
6201        if state.index >= state.items.len() {
6202            return Err(ZuzuRustError::runtime("iterator exhausted"));
6203        }
6204        let value = state.items[state.index].clone();
6205        state.index += 1;
6206        Ok(value)
6207    }
6208
6209    fn eval_new_expression(
6210        &self,
6211        argument: &Expression,
6212        traits: &[String],
6213        env: Rc<Environment>,
6214    ) -> Result<Value> {
6215        match argument {
6216            Expression::Call {
6217                callee, arguments, ..
6218            } if matches!(callee.as_ref(), Expression::MemberAccess { .. }) => {
6219                let (object, member) = match callee.as_ref() {
6220                    Expression::MemberAccess { object, member, .. } => {
6221                        (object.as_ref(), member.as_str())
6222                    }
6223                    _ => unreachable!(),
6224                };
6225                let (args, named_args) = self.eval_call_arguments(arguments, Rc::clone(&env))?;
6226                let mut receiver = self.eval_new_expression(object, &[], env)?;
6227                self.call_method_named(&mut receiver, member, &args, named_args)
6228            }
6229            Expression::MemberAccess { object, member, .. } => {
6230                let mut receiver = self.eval_new_expression(object, &[], env)?;
6231                self.call_method(&mut receiver, member, &[])
6232            }
6233            Expression::Call {
6234                callee, arguments, ..
6235            } => {
6236                let mut callee = self.eval_expression(callee, Rc::clone(&env))?;
6237                if !traits.is_empty() {
6238                    callee = Value::UserClass(self.per_object_trait_class(
6239                        callee,
6240                        traits,
6241                        Rc::clone(&env),
6242                    )?);
6243                }
6244                let (args, named_args) = self.eval_call_arguments(arguments, env)?;
6245                self.call_value(callee, args, named_args)
6246            }
6247            _ => Err(ZuzuRustError::runtime(
6248                "new expects a constructor call expression",
6249            )),
6250        }
6251    }
6252
6253    fn per_object_trait_class(
6254        &self,
6255        base_value: Value,
6256        trait_names: &[String],
6257        env: Rc<Environment>,
6258    ) -> Result<Rc<UserClassValue>> {
6259        let (class_name, base, base_key) = match base_value {
6260            Value::UserClass(class) => (
6261                class.name.clone(),
6262                ClassBase::User(Rc::clone(&class)),
6263                format!("u:{:p}", Rc::as_ptr(&class)),
6264            ),
6265            Value::Class(name) => (
6266                name.as_ref().clone(),
6267                ClassBase::Builtin(name.as_ref().clone()),
6268                format!("b:{}", name),
6269            ),
6270            other => {
6271                return Err(ZuzuRustError::runtime(format!(
6272                    "new with traits expects a Class, got {}",
6273                    self.typeof_name(&other)
6274                )))
6275            }
6276        };
6277
6278        let mut traits = Vec::new();
6279        let mut key_parts = vec![base_key];
6280        for trait_name in trait_names {
6281            match env.get(trait_name)? {
6282                Value::Trait(trait_value) => {
6283                    key_parts.push(format!("t:{:p}", Rc::as_ptr(&trait_value)));
6284                    traits.push(trait_value);
6285                }
6286                other => {
6287                    return Err(ZuzuRustError::runtime(format!(
6288                        "'{}' is not a trait (got {})",
6289                        trait_name,
6290                        self.typeof_name(&other)
6291                    )))
6292                }
6293            }
6294        }
6295        let cache_key = key_parts.join("\u{1f}");
6296        if let Some(class) = self.per_object_trait_class_cache.borrow().get(&cache_key) {
6297            return Ok(Rc::clone(class));
6298        }
6299
6300        let class_env = Rc::new(Environment::new(Some(env)));
6301        class_env.define(
6302            "__zuzu_per_object_base".to_owned(),
6303            match &base {
6304                ClassBase::User(class) => Value::UserClass(Rc::clone(class)),
6305                ClassBase::Builtin(name) => Value::Class(Rc::new(name.clone())),
6306            },
6307            false,
6308        );
6309        let source_trait_names = traits
6310            .iter()
6311            .enumerate()
6312            .map(|(index, trait_value)| {
6313                let name = format!("__zuzu_per_object_trait_{index}");
6314                class_env.define(name.clone(), Value::Trait(Rc::clone(trait_value)), false);
6315                name
6316            })
6317            .collect::<Vec<_>>();
6318
6319        let class = Rc::new(UserClassValue {
6320            name: class_name.clone(),
6321            base: Some(base),
6322            traits,
6323            fields: Vec::new(),
6324            methods: HashMap::new(),
6325            static_methods: HashMap::new(),
6326            nested_classes: HashMap::new(),
6327            source_decl: Some(ClassDeclaration {
6328                line: 0,
6329                source_file: None,
6330                name: class_name,
6331                base: Some("__zuzu_per_object_base".to_owned()),
6332                traits: source_trait_names,
6333                body: Vec::new(),
6334                shorthand: true,
6335            }),
6336            closure_env: Some(class_env),
6337        });
6338        self.per_object_trait_class_cache
6339            .borrow_mut()
6340            .insert(cache_key, Rc::clone(&class));
6341        Ok(class)
6342    }
6343
6344    fn construct_builtin_class(
6345        &self,
6346        name: &str,
6347        args: Vec<Value>,
6348        named_args: Vec<(String, Value)>,
6349    ) -> Result<Value> {
6350        match name {
6351            "Pair" => construct_pair(args, named_args),
6352            "PairList" => construct_pairlist(args, named_args),
6353            "Array" => {
6354                reject_named_args(name, &named_args)?;
6355                Ok(Value::Array(args))
6356            }
6357            "Bag" => {
6358                reject_named_args(name, &named_args)?;
6359                Ok(Value::Bag(args))
6360            }
6361            "Set" => {
6362                reject_named_args(name, &named_args)?;
6363                let mut items = Vec::new();
6364                for value in args {
6365                    push_unique(&mut items, value);
6366                }
6367                Ok(Value::Set(items))
6368            }
6369            "Dict" => {
6370                reject_named_args(name, &named_args)?;
6371                let mut map = HashMap::new();
6372                for pair in args {
6373                    let (key, value) = expect_pair_like(&pair)?;
6374                    map.insert(key, value);
6375                }
6376                Ok(Value::Dict(map))
6377            }
6378            "Channel" => {
6379                reject_named_args(name, &named_args)?;
6380                if !args.is_empty() {
6381                    return Err(ZuzuRustError::runtime("Channel() expects no arguments"));
6382                }
6383                Ok(Value::Channel(Rc::new(RefCell::new(ChannelState {
6384                    messages: Vec::new(),
6385                    closed: false,
6386                }))))
6387            }
6388            "CancellationSource" => {
6389                reject_named_args(name, &named_args)?;
6390                if !args.is_empty() {
6391                    return Err(ZuzuRustError::runtime(
6392                        "CancellationSource() expects no arguments",
6393                    ));
6394                }
6395                Ok(Value::CancellationSource(Rc::new(RefCell::new(
6396                    CancellationState {
6397                        cancelled: false,
6398                        reason: Value::Null,
6399                        watched: Vec::new(),
6400                    },
6401                ))))
6402            }
6403            "Path" | "JSON" | "YAML" | "CSV" | "Time" | "TimeZone" | "Duration" | "TimeFormat"
6404            | "TimeParser" | "CookieJar" | "UserAgent" | "Mailer" | "CLib" | "Widget"
6405            | "Window" | "VBox" | "HBox" | "Frame" | "Label" | "Text" | "RichText" | "Image"
6406            | "Input" | "DatePicker" | "Checkbox" | "Radio" | "RadioGroup" | "Select" | "Menu"
6407            | "MenuItem" | "Button" | "Separator" | "Slider" | "Progress" | "Tabs" | "Tab"
6408            | "ListView" | "TreeView" | "Event" | "ListenerToken" => {
6409                stdlib::construct_builtin_object(self, name, args, named_args)
6410                    .unwrap_or_else(|| unreachable!())
6411            }
6412            "Exception"
6413            | "ExhaustedException"
6414            | "TypeException"
6415            | "CancelledException"
6416            | "TimeoutException"
6417            | "ChannelClosedException"
6418            | "MarshallingException"
6419            | "UnmarshallingException" => {
6420                let mut message = name.to_owned();
6421                for (key, value) in named_args {
6422                    if key == "message" {
6423                        message = format!("{name}: {}", self.render_value(&value)?);
6424                    }
6425                }
6426                if args.len() == 1 {
6427                    message = format!("{name}: {}", self.render_value(&args[0])?);
6428                }
6429                Ok(Value::String(message))
6430            }
6431            other => Err(ZuzuRustError::runtime(format!(
6432                "cannot call class '{}' yet",
6433                other
6434            ))),
6435        }
6436    }
6437
6438    fn construct_user_class(
6439        &self,
6440        class: Rc<UserClassValue>,
6441        args: Vec<Value>,
6442        named_args: Vec<(String, Value)>,
6443    ) -> Result<Value> {
6444        self.construct_user_class_inner(class, args, named_args, true)
6445    }
6446
6447    pub(in crate::runtime) fn make_user_instance_without_build(
6448        &self,
6449        class: Rc<UserClassValue>,
6450        slots: HashMap<String, Value>,
6451    ) -> Result<Value> {
6452        self.construct_user_class_inner(class, Vec::new(), slots.into_iter().collect(), false)
6453    }
6454
6455    fn construct_user_class_inner(
6456        &self,
6457        class: Rc<UserClassValue>,
6458        args: Vec<Value>,
6459        named_args: Vec<(String, Value)>,
6460        call_build: bool,
6461    ) -> Result<Value> {
6462        let builtin_value = match self.class_builtin_base_name(&class) {
6463            Some(base) if base == "Array" => {
6464                Some(self.construct_builtin_class("Array", args.clone(), Vec::new())?)
6465            }
6466            Some(base) if base == "Bag" => {
6467                Some(self.construct_builtin_class("Bag", args.clone(), Vec::new())?)
6468            }
6469            Some(base) if base == "Set" => {
6470                Some(self.construct_builtin_class("Set", args.clone(), Vec::new())?)
6471            }
6472            Some(base) if base == "Dict" => {
6473                Some(self.construct_builtin_class("Dict", args.clone(), Vec::new())?)
6474            }
6475            Some(_) => {
6476                if !args.is_empty() {
6477                    return Err(ZuzuRustError::runtime(format!(
6478                        "constructor for '{}' does not accept positional arguments yet",
6479                        class.name
6480                    )));
6481                }
6482                None
6483            }
6484            None => {
6485                if !args.is_empty() {
6486                    return Err(ZuzuRustError::runtime(format!(
6487                        "constructor for '{}' does not accept positional arguments yet",
6488                        class.name
6489                    )));
6490                }
6491                None
6492            }
6493        };
6494
6495        let object = Rc::new(RefCell::new(ObjectValue {
6496            class: Rc::clone(&class),
6497            fields: HashMap::new(),
6498            weak_fields: HashSet::new(),
6499            builtin_value,
6500        }));
6501
6502        let fields = self.collect_field_specs(&class);
6503        for field in &fields {
6504            let value = match &field.default_value {
6505                Some(default_value) => {
6506                    self.eval_expression(default_value, Rc::clone(&self.class_decl_env(&class)))?
6507                }
6508                None => Value::Null,
6509            };
6510            self.object_set_field(&object, field, value)?;
6511        }
6512
6513        for (name, value) in named_args {
6514            let field = fields
6515                .iter()
6516                .find(|field| field.name == name)
6517                .ok_or_else(|| {
6518                    ZuzuRustError::runtime(format!(
6519                        "constructor for '{}' does not have a '{}' field",
6520                        class.name, name
6521                    ))
6522                })?;
6523            self.object_set_field(&object, field, value)?;
6524        }
6525
6526        if call_build && self.object_has_method(&object, "__build__") {
6527            let _ = self.call_object_method(&object, "__build__", &[], Vec::new())?;
6528        }
6529
6530        Ok(Value::Object(object))
6531    }
6532
6533    pub(in crate::runtime) fn marshal_builtin_env(&self) -> Rc<Environment> {
6534        let env = Rc::new(Environment::new(None));
6535        self.install_builtins(&env);
6536        env
6537    }
6538
6539    pub(in crate::runtime) fn marshal_current_or_builtin_env(&self) -> Rc<Environment> {
6540        self.current_env()
6541            .unwrap_or_else(|| self.marshal_builtin_env())
6542    }
6543
6544    pub(in crate::runtime) fn marshal_child_env(&self, parent: Rc<Environment>) -> Rc<Environment> {
6545        Rc::new(Environment::new(Some(parent)))
6546    }
6547
6548    pub(in crate::runtime) fn marshal_define_env(
6549        &self,
6550        env: &Rc<Environment>,
6551        name: &str,
6552        value: Value,
6553        mutable: bool,
6554    ) {
6555        env.define(name.to_owned(), value, mutable);
6556    }
6557
6558    pub(in crate::runtime) fn marshal_refresh_env(
6559        &self,
6560        env: &Rc<Environment>,
6561        name: &str,
6562        value: Value,
6563    ) -> bool {
6564        env.refresh_existing_binding(name, value)
6565    }
6566
6567    pub(in crate::runtime) fn marshal_load_module_export(
6568        &self,
6569        module_name: &str,
6570        export_name: &str,
6571    ) -> Result<Value> {
6572        self.load_module_exports(module_name)?
6573            .get(export_name)
6574            .cloned()
6575            .ok_or_else(|| {
6576                ZuzuRustError::runtime(format!(
6577                    "module '{}' does not export '{}'",
6578                    module_name, export_name
6579                ))
6580            })
6581    }
6582
6583    pub(in crate::runtime) fn marshal_binding(
6584        &self,
6585        env: &Rc<Environment>,
6586        name: &str,
6587    ) -> Option<(Value, bool)> {
6588        env.find_binding(name)
6589            .map(|binding| (binding.value.clone(), !binding.mutable))
6590    }
6591
6592    #[allow(dead_code)]
6593    pub(in crate::runtime) fn eval_marshal_code_value(
6594        &self,
6595        source: &str,
6596        binding_name: &str,
6597    ) -> Result<Value> {
6598        let parent = self
6599            .current_env()
6600            .unwrap_or_else(|| self.marshal_builtin_env());
6601        let env = self.marshal_child_env(parent);
6602        self.eval_marshal_code_value_in_env(source, binding_name, env, false)
6603    }
6604
6605    pub(in crate::runtime) fn eval_marshal_code_value_in_env(
6606        &self,
6607        source: &str,
6608        binding_name: &str,
6609        env: Rc<Environment>,
6610        expression_result: bool,
6611    ) -> Result<Value> {
6612        let source = if expression_result {
6613            format!("let __zuzu_marshal_value := {source}; __zuzu_marshal_value;")
6614        } else {
6615            source.to_owned()
6616        };
6617        let options = ParseOptions::new(false, self.infer_types, self.optimizations.clone());
6618        let program = parse_program_with_compile_options_and_source_file(
6619            &source,
6620            &options,
6621            Some("<std/marshal-code>"),
6622        )?;
6623        match self.eval_statements(&program.statements, Rc::clone(&env))? {
6624            ControlFlow::Normal => {
6625                if expression_result {
6626                    env.get("__zuzu_marshal_value")
6627                } else {
6628                    env.get(binding_name)
6629                }
6630            }
6631            ControlFlow::Return(_) => Err(ZuzuRustError::runtime(
6632                "return is not valid at top-level scope",
6633            )),
6634            ControlFlow::Throw(value) => Err(ZuzuRustError::thrown(self.render_value(&value)?)),
6635            ControlFlow::Break | ControlFlow::Continue => Err(ZuzuRustError::runtime(
6636                "loop control escaped marshal code record",
6637            )),
6638        }
6639    }
6640
6641    pub(in crate::runtime) fn marshal_bind_method(
6642        &self,
6643        receiver: Value,
6644        method_name: &str,
6645    ) -> Result<Value> {
6646        match receiver.clone() {
6647            Value::Object(object) => {
6648                let class = object.borrow().class.clone();
6649                let method = self.find_method(&class, method_name).ok_or_else(|| {
6650                    ZuzuRustError::runtime(format!("method '{}' was not found", method_name))
6651                })?;
6652                Ok(Value::Method(Rc::new(MethodValue {
6653                    name: method.name.clone(),
6654                    params: method.params.clone(),
6655                    return_type: method.return_type.clone(),
6656                    body: method.body.clone(),
6657                    env: Rc::clone(&method.env),
6658                    is_static: method.is_static,
6659                    is_async: method.is_async,
6660                    is_bodyless: method.is_bodyless,
6661                    bound_receiver: Some(receiver),
6662                    bound_name: Some(method_name.to_owned()),
6663                })))
6664            }
6665            Value::UserClass(class) => {
6666                let method = self
6667                    .find_static_method(&class, method_name)
6668                    .ok_or_else(|| {
6669                        ZuzuRustError::runtime(format!("method '{}' was not found", method_name))
6670                    })?;
6671                Ok(Value::Method(Rc::new(MethodValue {
6672                    name: method.name.clone(),
6673                    params: method.params.clone(),
6674                    return_type: method.return_type.clone(),
6675                    body: method.body.clone(),
6676                    env: Rc::clone(&method.env),
6677                    is_static: method.is_static,
6678                    is_async: method.is_async,
6679                    is_bodyless: method.is_bodyless,
6680                    bound_receiver: Some(receiver),
6681                    bound_name: Some(method_name.to_owned()),
6682                })))
6683            }
6684            _ => Err(ZuzuRustError::runtime(
6685                "bound method receiver must be an Object or Class",
6686            )),
6687        }
6688    }
6689
6690    pub(in crate::runtime) fn marshal_set_object_field(
6691        &self,
6692        object: &Rc<RefCell<ObjectValue>>,
6693        name: &str,
6694        value: Value,
6695        is_weak_storage: bool,
6696    ) -> Result<()> {
6697        let class = object.borrow().class.clone();
6698        if let Some(field) = self.find_field_spec(&class, name) {
6699            return self.object_set_field_with_weak_write(object, &field, value, is_weak_storage);
6700        }
6701        self.object_store_slot(object, name, value, is_weak_storage)?;
6702        Ok(())
6703    }
6704
6705    fn object_store_slot(
6706        &self,
6707        object: &Rc<RefCell<ObjectValue>>,
6708        name: &str,
6709        value: Value,
6710        weak_write: bool,
6711    ) -> Result<()> {
6712        let class = object.borrow().class.clone();
6713        if let Some(field) = self.find_field_spec(&class, name) {
6714            return self.object_set_field_with_weak_write(object, &field, value, weak_write);
6715        }
6716        let mut object = object.borrow_mut();
6717        if weak_write {
6718            object.weak_fields.insert(name.to_owned());
6719        } else {
6720            object.weak_fields.remove(name);
6721        }
6722        object
6723            .fields
6724            .insert(name.to_owned(), value.stored_with_weak_policy(weak_write));
6725        Ok(())
6726    }
6727
6728    pub(in crate::runtime) fn marshal_call_object_hook(
6729        &self,
6730        object: &Rc<RefCell<ObjectValue>>,
6731        name: &str,
6732    ) -> Result<()> {
6733        if self.object_has_method(object, name) {
6734            let _ = self.call_object_method(object, name, &[], Vec::new())?;
6735        }
6736        Ok(())
6737    }
6738
6739    fn call_ref(
6740        &self,
6741        reference: Rc<LvalueRef>,
6742        args: Vec<Value>,
6743        named_args: Vec<(String, Value)>,
6744    ) -> Result<Value> {
6745        if !named_args.is_empty() {
6746            return Err(ZuzuRustError::runtime(
6747                "lvalue refs do not accept named arguments",
6748            ));
6749        }
6750        match reference.as_ref() {
6751            LvalueRef::Expression { env, target } => match args.len() {
6752                0 => self.eval_expression(target, Rc::clone(env)),
6753                1 => self.assign_lvalue(
6754                    target,
6755                    args.into_iter().next().unwrap(),
6756                    false,
6757                    Rc::clone(env),
6758                ),
6759                2 => {
6760                    let mut args = args.into_iter();
6761                    let value = args.next().unwrap();
6762                    let weak_write = self.value_is_truthy(&args.next().unwrap())?;
6763                    self.assign_lvalue(target, value, weak_write, Rc::clone(env))
6764                }
6765                _ => Err(ZuzuRustError::runtime(
6766                    "lvalue refs accept zero, one, or two arguments",
6767                )),
6768            },
6769            LvalueRef::ObjectField { object, name } => match args.len() {
6770                0 => {
6771                    let value = object
6772                        .upgrade()
6773                        .and_then(|object| object.borrow().fields.get(name).cloned())
6774                        .unwrap_or(Value::Null);
6775                    Ok(if value.is_weak_value() {
6776                        value.resolve_weak_value()
6777                    } else {
6778                        value
6779                    })
6780                }
6781                1 => {
6782                    let Some(object) = object.upgrade() else {
6783                        return Ok(Value::Null);
6784                    };
6785                    let value = args.into_iter().next().unwrap();
6786                    self.object_store_slot(&object, name, value.clone(), false)?;
6787                    Ok(value)
6788                }
6789                2 => {
6790                    let Some(object) = object.upgrade() else {
6791                        return Ok(Value::Null);
6792                    };
6793                    let mut args = args.into_iter();
6794                    let value = args.next().unwrap();
6795                    let weak_write = self.value_is_truthy(&args.next().unwrap())?;
6796                    self.object_store_slot(&object, name, value.clone(), weak_write)?;
6797                    Ok(value)
6798                }
6799                _ => Err(ZuzuRustError::runtime(
6800                    "lvalue refs accept zero, one, or two arguments",
6801                )),
6802            },
6803        }
6804    }
6805
6806    fn bind_function_params(
6807        &self,
6808        function: &FunctionValue,
6809        env: &Environment,
6810        args: Vec<Value>,
6811        named_args: Vec<(String, Value)>,
6812    ) -> Result<()> {
6813        let mut arg_index = 0usize;
6814        let mut variadic_seen = false;
6815        let has_variadic_param = function.params.iter().any(|param| param.variadic);
6816        let named_pairlist_param = function
6817            .params
6818            .iter()
6819            .any(|param| has_variadic_param && param.declared_type.as_deref() == Some("PairList"));
6820        if !named_args.is_empty() && !named_pairlist_param {
6821            return Err(ZuzuRustError::thrown(
6822                "Named arguments are not accepted by this function call",
6823            ));
6824        }
6825        for (index, param) in function.params.iter().enumerate() {
6826            let fixed_remaining_after_current = function.params[index + 1..]
6827                .iter()
6828                .filter(|later| {
6829                    !named_pairlist_param || later.declared_type.as_deref() != Some("PairList")
6830                })
6831                .count();
6832            let value = if has_variadic_param && param.declared_type.as_deref() == Some("PairList")
6833            {
6834                Value::PairList(named_args.clone())
6835            } else if named_pairlist_param
6836                && param.declared_type.as_deref() == Some("Array")
6837                && fixed_remaining_after_current == 0
6838            {
6839                let rest = args[arg_index..].to_vec();
6840                arg_index = args.len();
6841                Value::Array(rest)
6842            } else if param.variadic {
6843                variadic_seen = true;
6844                let rest = args[arg_index..].to_vec();
6845                arg_index = args.len();
6846                Value::Array(rest)
6847            } else if param.declared_type.as_deref() == Some("Array")
6848                && args.len().saturating_sub(arg_index) > fixed_remaining_after_current + 1
6849            {
6850                let take = args.len() - arg_index - fixed_remaining_after_current;
6851                let rest = args[arg_index..arg_index + take].to_vec();
6852                arg_index += take;
6853                Value::Array(rest)
6854            } else if let Some(value) = args.get(arg_index).cloned() {
6855                arg_index += 1;
6856                value
6857            } else if let Some(default) = &param.default_value {
6858                self.eval_expression(
6859                    default,
6860                    Rc::new(Environment::new(Some(Rc::clone(&function.env)))),
6861                )?
6862            } else if param.optional {
6863                Value::Null
6864            } else {
6865                return Err(ZuzuRustError::thrown(
6866                    "Wrong number of arguments for function call",
6867                ));
6868            };
6869            if !(param.optional && matches!(value, Value::Null)) {
6870                self.assert_declared_type(param.declared_type.as_deref(), &value, &param.name)?;
6871            }
6872            env.define(param.name.clone(), value, false);
6873        }
6874        if arg_index < args.len() && !variadic_seen {
6875            return Err(ZuzuRustError::thrown(
6876                "Wrong number of arguments for function call",
6877            ));
6878        }
6879        Ok(())
6880    }
6881
6882    fn concat_values(&self, lhs: Value, rhs: Value) -> Result<Value> {
6883        match (lhs, rhs) {
6884            (Value::BinaryString(mut left), Value::BinaryString(right)) => {
6885                left.extend(right);
6886                Ok(Value::BinaryString(left))
6887            }
6888            (Value::String(left), Value::BinaryString(right)) => {
6889                Ok(Value::String(left + &self.binary_ascii_string(&right)?))
6890            }
6891            (Value::BinaryString(left), Value::String(right)) => {
6892                Ok(Value::String(self.binary_ascii_string(&left)? + &right))
6893            }
6894            (left, right) => Ok(Value::String(
6895                self.value_to_operator_string(&left)? + &self.value_to_operator_string(&right)?,
6896            )),
6897        }
6898    }
6899
6900    fn binary_ascii_string(&self, bytes: &[u8]) -> Result<String> {
6901        if bytes.iter().all(|byte| byte.is_ascii()) {
6902            Ok(bytes.iter().map(|byte| *byte as char).collect())
6903        } else {
6904            Err(ZuzuRustError::thrown(
6905                "Cannot implicitly concatenate non-ASCII BinaryString",
6906            ))
6907        }
6908    }
6909
6910    fn eval_bitwise(&self, operator: &str, lhs: Value, rhs: Value) -> Result<Value> {
6911        match (lhs, rhs) {
6912            (Value::BinaryString(left), Value::BinaryString(right)) => {
6913                if left.len() != right.len() {
6914                    return Err(ZuzuRustError::thrown(
6915                        "BinaryString bitwise operands must be equal length",
6916                    ));
6917                }
6918                let op = match operator {
6919                    "&" => |a, b| a & b,
6920                    "|" => |a, b| a | b,
6921                    "^" => |a, b| a ^ b,
6922                    _ => unreachable!(),
6923                };
6924                Ok(Value::BinaryString(
6925                    left.into_iter().zip(right).map(|(a, b)| op(a, b)).collect(),
6926                ))
6927            }
6928            (left, right) => {
6929                let lhs = self.value_to_number(&left)? as i64;
6930                let rhs = self.value_to_number(&right)? as i64;
6931                let value = match operator {
6932                    "&" => lhs & rhs,
6933                    "|" => lhs | rhs,
6934                    "^" => lhs ^ rhs,
6935                    _ => unreachable!(),
6936                };
6937                Ok(Value::Number(value as f64))
6938            }
6939        }
6940    }
6941
6942    fn eval_shift(&self, operator: &str, lhs: Value, rhs: Value) -> Result<Value> {
6943        // BinaryStrings shift as one whole bit string: bits carry across
6944        // byte boundaries, the length is preserved, vacated bits are 0.
6945        fn shift_bytes(bytes: &[u8], count: u64, left: bool) -> Vec<u8> {
6946            let len = bytes.len();
6947            if len == 0 || count >= len as u64 * 8 {
6948                return vec![0; len];
6949            }
6950            let byte_shift = (count / 8) as usize;
6951            let bit_shift = (count % 8) as u32;
6952            let mut out = vec![0u8; len];
6953            for (i, slot) in out.iter_mut().enumerate() {
6954                let value = if left {
6955                    let src = i + byte_shift;
6956                    let hi = if src < len { bytes[src] as u16 } else { 0 };
6957                    let lo = if src + 1 < len {
6958                        bytes[src + 1] as u16
6959                    } else {
6960                        0
6961                    };
6962                    ((hi << 8 | lo) << bit_shift) >> 8
6963                } else {
6964                    if i < byte_shift {
6965                        continue;
6966                    }
6967                    let lo = bytes[i - byte_shift] as u16;
6968                    let hi = if i > byte_shift {
6969                        (bytes[i - byte_shift - 1] as u16) << 8
6970                    } else {
6971                        0
6972                    };
6973                    (hi | lo) >> bit_shift
6974                };
6975                *slot = (value & 0xFF) as u8;
6976            }
6977            out
6978        }
6979
6980        let left_shift = matches!(operator, "<<" | "«");
6981        let count = self.value_to_number(&rhs)?.trunc();
6982        if !(count >= 0.0) || !count.is_finite() {
6983            return Err(ZuzuRustError::thrown(
6984                "shift count must be a non-negative integer",
6985            ));
6986        }
6987        match lhs {
6988            Value::BinaryString(bytes) => Ok(Value::BinaryString(shift_bytes(
6989                &bytes,
6990                count.min(u64::MAX as f64) as u64,
6991                left_shift,
6992            ))),
6993            other => {
6994                let value = self.value_to_number(&other)?.trunc();
6995                let factor = 2f64.powf(count);
6996                let shifted = if left_shift {
6997                    value * factor
6998                } else {
6999                    (value / factor).floor()
7000                };
7001                Ok(Value::Number(shifted))
7002            }
7003        }
7004    }
7005
7006    fn assign_index_target(
7007        &self,
7008        object: &Expression,
7009        index: &Expression,
7010        value: Value,
7011        weak_write: bool,
7012        env: Rc<Environment>,
7013    ) -> Result<Value> {
7014        let index_value = self.eval_expression(index, Rc::clone(&env))?;
7015        let object_value = self.eval_expression(object, Rc::clone(&env))?;
7016        if let Value::Shared(shared) = &object_value {
7017            let mut current = shared.borrow().clone();
7018            return match &mut current {
7019                Value::Array(values) => {
7020                    let idx = self.value_to_number(&index_value)? as usize;
7021                    if idx >= values.len() {
7022                        values.resize(idx + 1, Value::Null);
7023                    }
7024                    values[idx] = value.clone().stored_with_weak_policy(weak_write);
7025                    *shared.borrow_mut() = current;
7026                    Ok(value)
7027                }
7028                Value::String(text) => {
7029                    let replacement = match value {
7030                        Value::String(text) => text,
7031                        _ => {
7032                            return Err(ZuzuRustError::runtime(
7033                                "string index assignment requires a String value",
7034                            ))
7035                        }
7036                    };
7037                    let (from, to) = self.string_index_range(text, &index_value)?;
7038                    let updated = replace_char_range(text, from, to, replacement.chars());
7039                    *shared.borrow_mut() = Value::String(updated);
7040                    Ok(Value::String(replacement))
7041                }
7042                Value::BinaryString(bytes) => {
7043                    let replacement = match value {
7044                        Value::BinaryString(bytes) => bytes,
7045                        _ => {
7046                            return Err(ZuzuRustError::runtime(
7047                                "binary string index assignment requires a BinaryString value",
7048                            ))
7049                        }
7050                    };
7051                    let (from, to) = self.binary_index_range(bytes, &index_value)?;
7052                    bytes.splice(from..to, replacement.clone());
7053                    *shared.borrow_mut() = current;
7054                    Ok(Value::BinaryString(replacement))
7055                }
7056                Value::SystemArray(_) => Err(ZuzuRustError::runtime("Cannot modify __system__")),
7057                other => Err(ZuzuRustError::runtime(format!(
7058                    "index assignment requires an Array, String, or BinaryString value, got {}",
7059                    self.typeof_name(other)
7060                ))),
7061            };
7062        }
7063        if let Value::Ref(reference) | Value::AliasRef(reference) = object_value {
7064            return match self.deref_value(&Value::AliasRef(Rc::clone(&reference)))? {
7065                Value::Array(mut values) => {
7066                    let idx = self.value_to_number(&index_value)? as usize;
7067                    if idx >= values.len() {
7068                        values.resize(idx + 1, Value::Null);
7069                    }
7070                    values[idx] = value.clone().stored_with_weak_policy(weak_write);
7071                    let _ = self.assign_reference(reference, Value::Array(values))?;
7072                    Ok(value)
7073                }
7074                Value::String(text) => {
7075                    let replacement = match value {
7076                        Value::String(text) => text,
7077                        _ => {
7078                            return Err(ZuzuRustError::runtime(
7079                                "string index assignment requires a String value",
7080                            ))
7081                        }
7082                    };
7083                    let (from, to) = self.string_index_range(&text, &index_value)?;
7084                    let updated = replace_char_range(&text, from, to, replacement.chars());
7085                    let _ = self.assign_reference(reference, Value::String(updated))?;
7086                    Ok(Value::String(replacement))
7087                }
7088                Value::BinaryString(mut bytes) => {
7089                    let replacement = match value {
7090                        Value::BinaryString(bytes) => bytes,
7091                        _ => {
7092                            return Err(ZuzuRustError::runtime(
7093                                "binary string index assignment requires a BinaryString value",
7094                            ))
7095                        }
7096                    };
7097                    let (from, to) = self.binary_index_range(&bytes, &index_value)?;
7098                    bytes.splice(from..to, replacement.clone());
7099                    let _ = self.assign_reference(reference, Value::BinaryString(bytes))?;
7100                    Ok(Value::BinaryString(replacement))
7101                }
7102                Value::SystemArray(_) => Err(ZuzuRustError::runtime("Cannot modify __system__")),
7103                other => Err(ZuzuRustError::runtime(format!(
7104                    "index assignment requires an Array, String, or BinaryString value, got {}",
7105                    self.typeof_name(&other)
7106                ))),
7107            };
7108        }
7109        match object_value {
7110            Value::Array(mut values) => {
7111                let idx = self.value_to_number(&index_value)? as usize;
7112                if idx >= values.len() {
7113                    values.resize(idx + 1, Value::Null);
7114                }
7115                values[idx] = value.clone().stored_with_weak_policy(weak_write);
7116                match object {
7117                    Expression::Identifier { name, .. } => {
7118                        env.assign(name, Value::Array(values))?;
7119                        Ok(value)
7120                    }
7121                    _ => {
7122                        self.assign_lvalue(object, Value::Array(values), false, env)?;
7123                        Ok(value)
7124                    }
7125                }
7126            }
7127            Value::String(text) => {
7128                let replacement = match value {
7129                    Value::String(text) => text,
7130                    _ => {
7131                        return Err(ZuzuRustError::runtime(
7132                            "string index assignment requires a String value",
7133                        ))
7134                    }
7135                };
7136                let (from, to) = self.string_index_range(&text, &index_value)?;
7137                let updated = replace_char_range(&text, from, to, replacement.chars());
7138                match object {
7139                    Expression::Identifier { name, .. } => {
7140                        env.assign(name, Value::String(updated))?;
7141                        Ok(Value::String(replacement))
7142                    }
7143                    _ => {
7144                        self.assign_lvalue(object, Value::String(updated), false, env)?;
7145                        Ok(Value::String(replacement))
7146                    }
7147                }
7148            }
7149            Value::BinaryString(mut bytes) => {
7150                let replacement = match value {
7151                    Value::BinaryString(bytes) => bytes,
7152                    _ => {
7153                        return Err(ZuzuRustError::runtime(
7154                            "binary string index assignment requires a BinaryString value",
7155                        ))
7156                    }
7157                };
7158                let (from, to) = self.binary_index_range(&bytes, &index_value)?;
7159                bytes.splice(from..to, replacement.clone());
7160                match object {
7161                    Expression::Identifier { name, .. } => {
7162                        env.assign(name, Value::BinaryString(bytes))?;
7163                        Ok(Value::BinaryString(replacement))
7164                    }
7165                    _ => {
7166                        self.assign_lvalue(object, Value::BinaryString(bytes), false, env)?;
7167                        Ok(Value::BinaryString(replacement))
7168                    }
7169                }
7170            }
7171            Value::SystemArray(_) => Err(ZuzuRustError::runtime("Cannot modify __system__")),
7172            other => Err(ZuzuRustError::runtime(format!(
7173                "index assignment requires an Array, String, or BinaryString value, got {}",
7174                self.typeof_name(&other)
7175            ))),
7176        }
7177    }
7178
7179    fn assign_dict_target(
7180        &self,
7181        object: &Expression,
7182        key: &DictKey,
7183        value: Value,
7184        weak_write: bool,
7185        env: Rc<Environment>,
7186    ) -> Result<Value> {
7187        let key_name = self.eval_dict_key(key, Rc::clone(&env))?;
7188        let object_value = self.eval_expression(object, Rc::clone(&env))?;
7189        if let Value::Shared(shared) = &object_value {
7190            let mut current = shared.borrow().clone();
7191            return match &mut current {
7192                Value::Dict(map) => {
7193                    map.insert(key_name, value.clone().stored_with_weak_policy(weak_write));
7194                    *shared.borrow_mut() = current;
7195                    Ok(value)
7196                }
7197                Value::SystemDict(_) => Err(ZuzuRustError::runtime("Cannot modify __system__")),
7198                Value::PairList(values) => {
7199                    if let Some((_, entry_value)) = values
7200                        .iter_mut()
7201                        .find(|(entry_key, _)| entry_key == &key_name)
7202                    {
7203                        *entry_value = value.clone().stored_with_weak_policy(weak_write);
7204                    } else {
7205                        values.push((key_name, value.clone().stored_with_weak_policy(weak_write)));
7206                    }
7207                    *shared.borrow_mut() = current;
7208                    Ok(value)
7209                }
7210                other => Err(ZuzuRustError::runtime(format!(
7211                    "unsupported assignment target: {}",
7212                    self.typeof_name(other)
7213                ))),
7214            };
7215        }
7216        if let Value::Ref(reference) | Value::AliasRef(reference) = object_value {
7217            return match self.deref_value(&Value::AliasRef(Rc::clone(&reference)))? {
7218                Value::Dict(mut map) => {
7219                    map.insert(key_name, value.clone().stored_with_weak_policy(weak_write));
7220                    let _ = self.assign_reference(reference, Value::Dict(map))?;
7221                    Ok(value)
7222                }
7223                Value::SystemDict(_) => Err(ZuzuRustError::runtime("Cannot modify __system__")),
7224                Value::PairList(mut values) => {
7225                    if let Some((_, entry_value)) = values
7226                        .iter_mut()
7227                        .find(|(entry_key, _)| entry_key == &key_name)
7228                    {
7229                        *entry_value = value.clone().stored_with_weak_policy(weak_write);
7230                    } else {
7231                        values.push((key_name, value.clone().stored_with_weak_policy(weak_write)));
7232                    }
7233                    let _ = self.assign_reference(reference, Value::PairList(values))?;
7234                    Ok(value)
7235                }
7236                Value::Object(object) => {
7237                    self.object_store_slot(&object, &key_name, value.clone(), weak_write)?;
7238                    Ok(value)
7239                }
7240                _ => Err(ZuzuRustError::runtime("unsupported assignment target")),
7241            };
7242        }
7243        match object_value {
7244            Value::Dict(mut map) => {
7245                map.insert(key_name, value.clone().stored_with_weak_policy(weak_write));
7246                match object {
7247                    Expression::Identifier { name, .. } => {
7248                        env.assign(name, Value::Dict(map))?;
7249                        Ok(value)
7250                    }
7251                    _ => {
7252                        self.assign_lvalue(object, Value::Dict(map), false, env)?;
7253                        Ok(value)
7254                    }
7255                }
7256            }
7257            Value::SystemDict(_) => Err(ZuzuRustError::runtime("Cannot modify __system__")),
7258            Value::PairList(mut values) => {
7259                if let Some((_, entry_value)) = values
7260                    .iter_mut()
7261                    .find(|(entry_key, _)| entry_key == &key_name)
7262                {
7263                    *entry_value = value.clone().stored_with_weak_policy(weak_write);
7264                } else {
7265                    values.push((key_name, value.clone().stored_with_weak_policy(weak_write)));
7266                }
7267                match object {
7268                    Expression::Identifier { name, .. } => {
7269                        env.assign(name, Value::PairList(values))?;
7270                        Ok(value)
7271                    }
7272                    _ => {
7273                        self.assign_lvalue(object, Value::PairList(values), false, env)?;
7274                        Ok(value)
7275                    }
7276                }
7277            }
7278            Value::Object(object) => {
7279                let existing = object.borrow().fields.get(&key_name).cloned();
7280                if let Some(Value::Ref(reference) | Value::AliasRef(reference)) = existing {
7281                    let _ = self.assign_reference_with_weak_write(
7282                        reference,
7283                        value.clone(),
7284                        weak_write,
7285                    )?;
7286                } else {
7287                    self.object_store_slot(&object, &key_name, value.clone(), weak_write)?;
7288                }
7289                Ok(value)
7290            }
7291            _ => Err(ZuzuRustError::runtime("unsupported assignment target")),
7292        }
7293    }
7294
7295    fn assign_slice_target(
7296        &self,
7297        object: &Expression,
7298        start: Option<&Expression>,
7299        end: Option<&Expression>,
7300        value: Value,
7301        env: Rc<Environment>,
7302    ) -> Result<Value> {
7303        let start_value = self.eval_optional_expr(start, Rc::clone(&env))?;
7304        let count_value = self.eval_optional_expr(end, Rc::clone(&env))?;
7305        if let Expression::Identifier { name, .. } = object {
7306            match env.get(name)? {
7307                Value::Shared(shared) => {
7308                    let mut current = shared.borrow().clone();
7309                    match &mut current {
7310                        Value::Array(values) => {
7311                            let replacement = match value {
7312                                Value::Array(values) => values,
7313                                _ => {
7314                                    return Err(ZuzuRustError::runtime(
7315                                        "slice assignment requires an Array value",
7316                                    ))
7317                                }
7318                            };
7319                            let start = match start_value {
7320                                Value::Null => 0,
7321                                ref other => self.value_to_number(other)? as usize,
7322                            };
7323                            let count = match count_value {
7324                                Value::Null => values.len().saturating_sub(start),
7325                                ref other => self.value_to_number(other)? as usize,
7326                            };
7327                            let from = start.min(values.len());
7328                            let to = (from + count).min(values.len());
7329                            values.splice(from..to, replacement.clone());
7330                            *shared.borrow_mut() = current;
7331                            Ok(Value::Array(replacement))
7332                        }
7333                        Value::String(text) => {
7334                            let replacement = match value {
7335                                Value::String(text) => text,
7336                                _ => {
7337                                    return Err(ZuzuRustError::runtime(
7338                                        "string slice assignment requires a String value",
7339                                    ))
7340                                }
7341                            };
7342                            let (from, to) =
7343                                self.string_slice_range(text, &start_value, &count_value)?;
7344                            let updated = replace_char_range(text, from, to, replacement.chars());
7345                            *shared.borrow_mut() = Value::String(updated);
7346                            Ok(Value::String(replacement))
7347                        }
7348                        Value::BinaryString(bytes) => {
7349                            let replacement = match value {
7350                                Value::BinaryString(bytes) => bytes,
7351                                _ => return Err(ZuzuRustError::runtime(
7352                                    "binary string slice assignment requires a BinaryString value",
7353                                )),
7354                            };
7355                            let (from, to) =
7356                                self.binary_slice_range(bytes, &start_value, &count_value)?;
7357                            bytes.splice(from..to, replacement.clone());
7358                            *shared.borrow_mut() = current;
7359                            Ok(Value::BinaryString(replacement))
7360                        }
7361                        Value::SystemArray(_) => {
7362                            Err(ZuzuRustError::runtime("Cannot modify __system__"))
7363                        }
7364                        _ => Err(ZuzuRustError::runtime(
7365                            "slice assignment requires an Array, String, or BinaryString value",
7366                        )),
7367                    }
7368                }
7369                Value::Array(mut values) => {
7370                    let replacement = match value {
7371                        Value::Array(values) => values,
7372                        _ => {
7373                            return Err(ZuzuRustError::runtime(
7374                                "slice assignment requires an Array value",
7375                            ))
7376                        }
7377                    };
7378                    let start = match start_value {
7379                        Value::Null => 0,
7380                        ref other => self.value_to_number(other)? as usize,
7381                    };
7382                    let count = match count_value {
7383                        Value::Null => values.len().saturating_sub(start),
7384                        ref other => self.value_to_number(other)? as usize,
7385                    };
7386                    let from = start.min(values.len());
7387                    let to = (from + count).min(values.len());
7388                    values.splice(from..to, replacement.clone());
7389                    env.assign(name, Value::Array(values))?;
7390                    Ok(Value::Array(replacement))
7391                }
7392                Value::SystemArray(_) => Err(ZuzuRustError::runtime("Cannot modify __system__")),
7393                Value::String(text) => {
7394                    let replacement = match value {
7395                        Value::String(text) => text,
7396                        _ => {
7397                            return Err(ZuzuRustError::runtime(
7398                                "string slice assignment requires a String value",
7399                            ))
7400                        }
7401                    };
7402                    let (from, to) = self.string_slice_range(&text, &start_value, &count_value)?;
7403                    env.assign(
7404                        name,
7405                        Value::String(replace_char_range(&text, from, to, replacement.chars())),
7406                    )?;
7407                    Ok(Value::String(replacement))
7408                }
7409                Value::BinaryString(mut bytes) => {
7410                    let replacement = match value {
7411                        Value::BinaryString(bytes) => bytes,
7412                        _ => {
7413                            return Err(ZuzuRustError::runtime(
7414                                "binary string slice assignment requires a BinaryString value",
7415                            ))
7416                        }
7417                    };
7418                    let (from, to) = self.binary_slice_range(&bytes, &start_value, &count_value)?;
7419                    bytes.splice(from..to, replacement.clone());
7420                    env.assign(name, Value::BinaryString(bytes))?;
7421                    Ok(Value::BinaryString(replacement))
7422                }
7423                _ => Err(ZuzuRustError::runtime(
7424                    "slice assignment requires an Array, String, or BinaryString value",
7425                )),
7426            }
7427        } else {
7428            Err(ZuzuRustError::runtime("unsupported assignment target"))
7429        }
7430    }
7431
7432    fn string_slice_range(
7433        &self,
7434        text: &str,
7435        start_value: &Value,
7436        count_value: &Value,
7437    ) -> Result<(usize, usize)> {
7438        let len = text.chars().count() as isize;
7439        let mut start = match start_value {
7440            Value::Null => 0,
7441            other => self.value_to_number(other)? as isize,
7442        };
7443        if start < 0 {
7444            start += len;
7445        }
7446        start = start.clamp(0, len);
7447        let count = match count_value {
7448            Value::Null => len - start,
7449            other => self.value_to_number(other)? as isize,
7450        }
7451        .max(0);
7452        let end = (start + count).clamp(0, len);
7453        Ok((start as usize, end as usize))
7454    }
7455
7456    fn string_index_range(&self, text: &str, index_value: &Value) -> Result<(usize, usize)> {
7457        let len = text.chars().count() as isize;
7458        let mut index = self.value_to_number(index_value)? as isize;
7459        if index < 0 {
7460            index += len;
7461        }
7462        index = index.clamp(0, len);
7463        let end = (index + 1).clamp(0, len);
7464        Ok((index as usize, end as usize))
7465    }
7466
7467    fn binary_slice_range(
7468        &self,
7469        bytes: &[u8],
7470        start_value: &Value,
7471        count_value: &Value,
7472    ) -> Result<(usize, usize)> {
7473        let len = bytes.len() as isize;
7474        let mut start = match start_value {
7475            Value::Null => 0,
7476            other => self.value_to_number(other)? as isize,
7477        };
7478        if start < 0 {
7479            start += len;
7480        }
7481        start = start.clamp(0, len);
7482        let count = match count_value {
7483            Value::Null => len - start,
7484            other => self.value_to_number(other)? as isize,
7485        }
7486        .max(0);
7487        let end = (start + count).clamp(0, len);
7488        Ok((start as usize, end as usize))
7489    }
7490
7491    fn binary_index_range(&self, bytes: &[u8], index_value: &Value) -> Result<(usize, usize)> {
7492        let len = bytes.len() as isize;
7493        let mut index = self.value_to_number(index_value)? as isize;
7494        if index < 0 {
7495            index += len;
7496        }
7497        index = index.clamp(0, len);
7498        let end = (index + 1).clamp(0, len);
7499        Ok((index as usize, end as usize))
7500    }
7501
7502    fn apply_regex_replacement(
7503        &self,
7504        current: Value,
7505        replacement: &Expression,
7506        env: Rc<Environment>,
7507    ) -> Result<Value> {
7508        let source = self.value_to_operator_string(&current)?;
7509        let (regex_pattern, regex_flags, replacement_expr) = match replacement {
7510            Expression::Binary {
7511                operator,
7512                left,
7513                right,
7514                ..
7515            } if operator == "->" => {
7516                let regex_value = self.eval_expression(left, Rc::clone(&env))?;
7517                let (pattern, flags) = self.coerce_regex_operand(&regex_value).map_err(|_| {
7518                    ZuzuRustError::runtime("~= expects a regexp -> replacement expression")
7519                })?;
7520                (pattern, flags, right.as_ref())
7521            }
7522            _ => {
7523                return Err(ZuzuRustError::runtime(
7524                    "~= expects a regexp -> replacement expression",
7525                ))
7526            }
7527        };
7528        let compiled = self.compile_regex(&regex_pattern, &regex_flags)?;
7529        let mut out = String::new();
7530        let mut cursor = 0usize;
7531        let global = regex_flags.contains('g');
7532
7533        while cursor <= source.len() {
7534            let Some(captures) = compiled.captures(&source[cursor..]) else {
7535                break;
7536            };
7537            let Some(full) = captures.get(0) else {
7538                break;
7539            };
7540            let start = cursor + full.start();
7541            let end = cursor + full.end();
7542            out.push_str(&source[cursor..start]);
7543            let match_env = Rc::new(Environment::new(Some(Rc::clone(&env))));
7544            match_env.define(
7545                "m".to_owned(),
7546                Value::Array(
7547                    captures
7548                        .iter()
7549                        .map(|item| {
7550                            Value::String(item.map(|m| m.as_str()).unwrap_or("").to_owned())
7551                        })
7552                        .collect(),
7553                ),
7554                true,
7555            );
7556            let replacement_value =
7557                self.eval_expression(replacement_expr, Rc::clone(&match_env))?;
7558            out.push_str(&self.render_value(&replacement_value)?);
7559            cursor = end;
7560            if !global {
7561                break;
7562            }
7563            if end == start {
7564                break;
7565            }
7566        }
7567        out.push_str(&source[cursor..]);
7568        Ok(Value::String(out))
7569    }
7570
7571    pub(in crate::runtime) fn render_value(&self, value: &Value) -> Result<String> {
7572        let value = self.deref_value(value)?;
7573        match &value {
7574            Value::Object(object) if self.object_has_method(object, "to_String") => {
7575                let rendered = self.call_object_method(object, "to_String", &[], Vec::new())?;
7576                self.render_value(&rendered)
7577            }
7578            Value::Object(object) => {
7579                if let Some(rendered) = self.object_builtin_render(object)? {
7580                    Ok(rendered)
7581                } else {
7582                    Ok(value.render())
7583                }
7584            }
7585            _ => Ok(value.render()),
7586        }
7587    }
7588
7589    pub(in crate::runtime) fn value_to_operator_string(&self, value: &Value) -> Result<String> {
7590        let value = self.deref_value(value)?;
7591        match &value {
7592            Value::Null => Ok(String::new()),
7593            Value::Boolean(true) => Ok("true".to_owned()),
7594            Value::Boolean(false) => Ok("false".to_owned()),
7595            Value::Number(number) => Ok(render_number(*number)),
7596            Value::String(text) => Ok(text.clone()),
7597            Value::Regex(pattern, _) => Ok(pattern.clone()),
7598            Value::Object(object) if self.object_has_method(object, "to_String") => {
7599                let rendered = self.call_object_method(object, "to_String", &[], Vec::new())?;
7600                self.value_to_operator_string(&rendered)
7601            }
7602            _ => Err(ZuzuRustError::runtime(format!(
7603                "cannot coerce {} to String",
7604                self.typeof_name(&value)
7605            ))),
7606        }
7607    }
7608
7609    fn render_repl_value(&self, value: &Value) -> Result<String> {
7610        let value = self.deref_value(value)?;
7611        match &value {
7612            Value::Null => Ok("Null".to_owned()),
7613            Value::Boolean(_) | Value::Number(_) | Value::String(_) | Value::BinaryString(_) => {
7614                self.render_value(&value)
7615            }
7616            _ => Ok(self.typeof_name(&value)),
7617        }
7618    }
7619
7620    fn value_to_number(&self, value: &Value) -> Result<f64> {
7621        let value = self.deref_value(value)?;
7622        match &value {
7623            Value::Object(object) if self.object_has_method(object, "to_Number") => {
7624                let coerced = self.call_object_method(object, "to_Number", &[], Vec::new())?;
7625                self.value_to_number(&coerced)
7626            }
7627            _ => value.to_number(),
7628        }
7629    }
7630
7631    pub(in crate::runtime) fn value_is_truthy(&self, value: &Value) -> Result<bool> {
7632        let value = self.deref_value(value)?;
7633        match &value {
7634            Value::Object(object) if self.object_has_method(object, "to_Boolean") => {
7635                let coerced = self.call_object_method(object, "to_Boolean", &[], Vec::new())?;
7636                self.value_is_truthy(&coerced)
7637            }
7638            Value::Object(object) => {
7639                if let Some(result) = self.object_builtin_truthy(object) {
7640                    Ok(result)
7641                } else {
7642                    Ok(value.is_truthy())
7643                }
7644            }
7645            _ => Ok(value.is_truthy()),
7646        }
7647    }
7648
7649    fn typeof_name(&self, value: &Value) -> String {
7650        let value = self.deref_value(value).unwrap_or_else(|_| value.clone());
7651        match value {
7652            Value::Object(object) => object.borrow().class.name.clone(),
7653            Value::UserClass(_) | Value::Class(_) => "Class".to_owned(),
7654            Value::Trait(_) => "Trait".to_owned(),
7655            Value::Method(_) => "Method".to_owned(),
7656            _ => value.type_name().to_owned(),
7657        }
7658    }
7659
7660    fn member_name_operand(&self, expr: &Expression, env: Rc<Environment>) -> Result<String> {
7661        match expr {
7662            Expression::Identifier { name, .. } => Ok(name.clone()),
7663            Expression::StringLiteral { value, .. } => Ok(value.clone()),
7664            _ => self.render_value(&self.eval_expression(expr, env)?),
7665        }
7666    }
7667
7668    fn value_instanceof(&self, value: &Value, class_value: &Value) -> bool {
7669        let value = self.deref_value(value).unwrap_or_else(|_| value.clone());
7670        let class_value = self
7671            .deref_value(class_value)
7672            .unwrap_or_else(|_| class_value.clone());
7673        match (&value, &class_value) {
7674            (_, Value::Class(name)) if name.as_str() == "Any" => true,
7675            (Value::Class(_) | Value::UserClass(_), Value::Class(name)) => name.as_str() == "Class",
7676            (Value::Object(object), Value::UserClass(class)) => {
7677                self.class_matches_user(&object.borrow().class, class)
7678            }
7679            (Value::String(_), Value::UserClass(class)) => self.class_matches(class, "Exception"),
7680            (Value::Null, Value::Class(name)) => name.as_str() == "Null",
7681            (Value::Boolean(_), Value::Class(name)) => name.as_str() == "Boolean",
7682            (Value::Number(_), Value::Class(name)) => name.as_str() == "Number",
7683            (Value::String(_), Value::Class(name)) => name.as_str() == "String",
7684            (Value::BinaryString(_), Value::Class(name)) => name.as_str() == "BinaryString",
7685            (Value::Array(_) | Value::SystemArray(_), Value::Class(name)) => {
7686                matches!(name.as_str(), "Array" | "Collection" | "Object")
7687            }
7688            (Value::Set(_), Value::Class(name)) => {
7689                matches!(name.as_str(), "Set" | "Collection" | "Object")
7690            }
7691            (Value::Bag(_), Value::Class(name)) => {
7692                matches!(name.as_str(), "Bag" | "Collection" | "Object")
7693            }
7694            (Value::Dict(_) | Value::SystemDict(_), Value::Class(name)) => {
7695                matches!(name.as_str(), "Dict" | "Collection" | "Object")
7696            }
7697            (Value::PairList(_), Value::Class(name)) => name.as_str() == "PairList",
7698            (Value::Pair(_, _), Value::Class(name)) => name.as_str() == "Pair",
7699            (Value::Regex(_, _), Value::Class(name)) => name.as_str() == "Regexp",
7700            (Value::Object(object), Value::Class(name)) => {
7701                let object_class = &object.borrow().class;
7702                name.as_str() == "Object"
7703                    || (object_class.source_decl.is_none() && object_class.name == name.as_str())
7704                    || matches!(
7705                        (self.class_builtin_base_name(object_class), name.as_str()),
7706                        (Some(base), target) if base == target
7707                            || (
7708                                target == "Collection"
7709                                && matches!(base.as_str(), "Array" | "Set" | "Bag" | "Dict")
7710                            )
7711                    )
7712            }
7713            (
7714                Value::Function(_) | Value::NativeFunction(_) | Value::Iterator(_),
7715                Value::Class(name),
7716            ) => name.as_str() == "Function",
7717            (Value::Task(_), Value::Class(name)) => name.as_str() == "Task",
7718            (Value::Channel(_), Value::Class(name)) => name.as_str() == "Channel",
7719            (Value::CancellationSource(_), Value::Class(name)) => {
7720                name.as_str() == "CancellationSource"
7721            }
7722            (Value::CancellationToken(_), Value::Class(name)) => {
7723                name.as_str() == "CancellationToken"
7724            }
7725            _ => false,
7726        }
7727    }
7728
7729    fn value_does_trait(&self, value: &Value, trait_value: &Value) -> bool {
7730        let value = self.deref_value(value).unwrap_or_else(|_| value.clone());
7731        let trait_value = self
7732            .deref_value(trait_value)
7733            .unwrap_or_else(|_| trait_value.clone());
7734        let trait_name = match &trait_value {
7735            Value::Trait(trait_value) => trait_value.name.as_str(),
7736            Value::UserClass(class) => class.name.as_str(),
7737            Value::Class(name) => name.as_str(),
7738            _ => return false,
7739        };
7740        match &value {
7741            Value::Object(object) => self.class_has_trait(&object.borrow().class, trait_name),
7742            _ => false,
7743        }
7744    }
7745
7746    fn value_can_method(&self, value: &Value, name: &str) -> bool {
7747        let value = self.deref_value(value).unwrap_or_else(|_| value.clone());
7748        match &value {
7749            Value::Class(class_name) => stdlib::has_builtin_class_method(class_name, name),
7750            Value::Object(object) => self.object_has_method(object, name),
7751            _ => false,
7752        }
7753    }
7754
7755    fn class_matches(&self, class: &Rc<UserClassValue>, name: &str) -> bool {
7756        if class.name == name {
7757            return true;
7758        }
7759        match &class.base {
7760            Some(ClassBase::User(base)) => self.class_matches(base, name),
7761            Some(ClassBase::Builtin(base)) => base == name,
7762            None => false,
7763        }
7764    }
7765
7766    fn class_matches_user(&self, class: &Rc<UserClassValue>, target: &Rc<UserClassValue>) -> bool {
7767        if Rc::ptr_eq(class, target) {
7768            return true;
7769        }
7770        if class.name == target.name
7771            && is_builtin_exception_class(&class.name)
7772            && is_builtin_exception_class(&target.name)
7773        {
7774            return true;
7775        }
7776        match &class.base {
7777            Some(ClassBase::User(base)) => self.class_matches_user(base, target),
7778            Some(ClassBase::Builtin(_)) | None => false,
7779        }
7780    }
7781
7782    fn class_has_trait(&self, class: &Rc<UserClassValue>, name: &str) -> bool {
7783        if class
7784            .traits
7785            .iter()
7786            .any(|trait_value| trait_value.name == name)
7787        {
7788            return true;
7789        }
7790        match &class.base {
7791            Some(ClassBase::User(base)) => self.class_has_trait(base, name),
7792            None => false,
7793            Some(ClassBase::Builtin(_)) => false,
7794        }
7795    }
7796
7797    fn class_decl_env(&self, class: &Rc<UserClassValue>) -> Rc<Environment> {
7798        if let Some(method) = class.methods.values().next() {
7799            return Rc::clone(&method.env);
7800        }
7801        if let Some(method) = class.static_methods.values().next() {
7802            return Rc::clone(&method.env);
7803        }
7804        if let Some(base) = &class.base {
7805            if let ClassBase::User(base) = base {
7806                return self.class_decl_env(base);
7807            }
7808        }
7809        if let Some(trait_value) = class.traits.first() {
7810            if let Some(method) = trait_value.methods.values().next() {
7811                return Rc::clone(&method.env);
7812            }
7813        }
7814        if let Some(class) = class.nested_classes.values().next() {
7815            return self.class_decl_env(class);
7816        }
7817        Rc::new(Environment::new(None))
7818    }
7819
7820    fn find_method(&self, class: &Rc<UserClassValue>, name: &str) -> Option<Rc<MethodValue>> {
7821        if let Some(method) = class.methods.get(name) {
7822            return Some(Rc::clone(method));
7823        }
7824        for trait_value in &class.traits {
7825            if let Some(method) = trait_value.methods.get(name) {
7826                return Some(Rc::clone(method));
7827            }
7828        }
7829        match &class.base {
7830            Some(ClassBase::User(base)) => self.find_method(base, name),
7831            None => None,
7832            Some(ClassBase::Builtin(_)) => None,
7833        }
7834    }
7835
7836    fn collect_method_candidates(
7837        &self,
7838        class: &Rc<UserClassValue>,
7839        name: &str,
7840        is_static: bool,
7841        candidates: &mut Vec<Rc<MethodValue>>,
7842    ) {
7843        if is_static {
7844            if let Some(method) = class.static_methods.get(name) {
7845                candidates.push(Rc::clone(method));
7846            }
7847        } else {
7848            if let Some(method) = class.methods.get(name) {
7849                candidates.push(Rc::clone(method));
7850            }
7851            for trait_value in &class.traits {
7852                if let Some(method) = trait_value.methods.get(name) {
7853                    candidates.push(Rc::clone(method));
7854                }
7855            }
7856        }
7857
7858        if let Some(ClassBase::User(base)) = &class.base {
7859            self.collect_method_candidates(base, name, is_static, candidates);
7860        }
7861    }
7862
7863    fn find_next_method(
7864        &self,
7865        class: &Rc<UserClassValue>,
7866        name: &str,
7867        is_static: bool,
7868    ) -> Option<Rc<MethodValue>> {
7869        let current = self.current_method_stack.borrow().last().cloned()?;
7870        let mut candidates = Vec::new();
7871        self.collect_method_candidates(class, name, is_static, &mut candidates);
7872        for (index, candidate) in candidates.iter().enumerate() {
7873            if Rc::ptr_eq(candidate, &current) {
7874                return candidates.get(index + 1).cloned();
7875            }
7876        }
7877        None
7878    }
7879
7880    fn find_static_method(
7881        &self,
7882        class: &Rc<UserClassValue>,
7883        name: &str,
7884    ) -> Option<Rc<MethodValue>> {
7885        if let Some(method) = class.static_methods.get(name) {
7886            return Some(Rc::clone(method));
7887        }
7888        match &class.base {
7889            Some(ClassBase::User(base)) => self.find_static_method(base, name),
7890            None => None,
7891            Some(ClassBase::Builtin(_)) => None,
7892        }
7893    }
7894
7895    fn class_builtin_base_name(&self, class: &Rc<UserClassValue>) -> Option<String> {
7896        match &class.base {
7897            Some(ClassBase::Builtin(name)) => Some(name.clone()),
7898            Some(ClassBase::User(base)) => self.class_builtin_base_name(base),
7899            None => None,
7900        }
7901    }
7902
7903    fn object_builtin_value(&self, object: &Rc<RefCell<ObjectValue>>) -> Option<Value> {
7904        object.borrow().builtin_value.clone()
7905    }
7906
7907    fn object_builtin_collection_contains(
7908        &self,
7909        object: &Rc<RefCell<ObjectValue>>,
7910        needle: &Value,
7911    ) -> bool {
7912        match self.object_builtin_value(object) {
7913            Some(value) => collection_contains(&value, needle),
7914            None => false,
7915        }
7916    }
7917
7918    fn object_builtin_truthy(&self, object: &Rc<RefCell<ObjectValue>>) -> Option<bool> {
7919        self.object_builtin_value(object)
7920            .map(|value| value.is_truthy())
7921    }
7922
7923    fn object_builtin_render(&self, object: &Rc<RefCell<ObjectValue>>) -> Result<Option<String>> {
7924        match self.object_builtin_value(object) {
7925            Some(value) => Ok(Some(self.render_value(&value)?)),
7926            None => Ok(None),
7927        }
7928    }
7929
7930    fn collect_field_specs(&self, class: &Rc<UserClassValue>) -> Vec<FieldSpec> {
7931        let mut fields = match &class.base {
7932            Some(ClassBase::User(base)) => self.collect_field_specs(base),
7933            None => Vec::new(),
7934            Some(ClassBase::Builtin(_)) => Vec::new(),
7935        };
7936        fields.extend(class.fields.iter().cloned());
7937        fields
7938    }
7939
7940    fn find_field_spec<'a>(&self, class: &'a Rc<UserClassValue>, name: &str) -> Option<FieldSpec> {
7941        self.collect_field_specs(class)
7942            .into_iter()
7943            .find(|field| field.name == name)
7944    }
7945
7946    fn object_has_method(&self, object: &Rc<RefCell<ObjectValue>>, name: &str) -> bool {
7947        let object_ref = object.borrow();
7948        if self.class_matches(&object_ref.class, "Exception")
7949            && matches!(name, "to_String" | "message")
7950        {
7951            return true;
7952        }
7953        if self.find_method(&object_ref.class, name).is_some() {
7954            return true;
7955        }
7956        if stdlib::has_builtin_object_method(&object_ref.class.name, name) {
7957            return true;
7958        }
7959        self.find_field_spec(&object_ref.class, name.strip_prefix("get_").unwrap_or(""))
7960            .map(|field| {
7961                name.starts_with("get_") && field.accessors.iter().any(|item| item == "get")
7962            })
7963            .unwrap_or(false)
7964            || self
7965                .find_field_spec(&object_ref.class, name.strip_prefix("set_").unwrap_or(""))
7966                .map(|field| {
7967                    name.starts_with("set_") && field.accessors.iter().any(|item| item == "set")
7968                })
7969                .unwrap_or(false)
7970            || self
7971                .find_field_spec(&object_ref.class, name.strip_prefix("clear_").unwrap_or(""))
7972                .map(|field| {
7973                    name.starts_with("clear_") && field.accessors.iter().any(|item| item == "clear")
7974                })
7975                .unwrap_or(false)
7976            || self
7977                .find_field_spec(&object_ref.class, name.strip_prefix("has_").unwrap_or(""))
7978                .map(|field| {
7979                    name.starts_with("has_") && field.accessors.iter().any(|item| item == "has")
7980                })
7981                .unwrap_or(false)
7982    }
7983
7984    fn call_object_method(
7985        &self,
7986        object: &Rc<RefCell<ObjectValue>>,
7987        name: &str,
7988        args: &[Value],
7989        named_args: Vec<(String, Value)>,
7990    ) -> Result<Value> {
7991        let class = Rc::clone(&object.borrow().class);
7992        if let Some(field_name) = name.strip_prefix("get_") {
7993            if let Some(field) = self.find_field_spec(&class, field_name) {
7994                if field.accessors.iter().any(|item| item == "get") {
7995                    reject_named_args(name, &named_args)?;
7996                    require_arity(name, args, 0)?;
7997                    return Ok(object
7998                        .borrow()
7999                        .fields
8000                        .get(field_name)
8001                        .cloned()
8002                        .unwrap_or(Value::Null));
8003                }
8004            }
8005        }
8006        if let Some(field_name) = name.strip_prefix("set_") {
8007            if let Some(field) = self.find_field_spec(&class, field_name) {
8008                if field.accessors.iter().any(|item| item == "set") {
8009                    reject_named_args(name, &named_args)?;
8010                    require_arity(name, args, 1)?;
8011                    self.object_set_field(object, &field, args[0].clone())?;
8012                    return Ok(Value::Object(Rc::clone(object)));
8013                }
8014            }
8015        }
8016        if let Some(field_name) = name.strip_prefix("clear_") {
8017            if let Some(field) = self.find_field_spec(&class, field_name) {
8018                if field.accessors.iter().any(|item| item == "clear") {
8019                    reject_named_args(name, &named_args)?;
8020                    require_arity(name, args, 0)?;
8021                    self.object_set_field(object, &field, Value::Null)?;
8022                    return Ok(Value::Object(Rc::clone(object)));
8023                }
8024            }
8025        }
8026        if let Some(field_name) = name.strip_prefix("has_") {
8027            if let Some(field) = self.find_field_spec(&class, field_name) {
8028                if field.accessors.iter().any(|item| item == "has") {
8029                    reject_named_args(name, &named_args)?;
8030                    require_arity(name, args, 0)?;
8031                    let has_value = object
8032                        .borrow()
8033                        .fields
8034                        .get(field_name)
8035                        .map(|value| !matches!(value.resolve_weak_value(), Value::Null))
8036                        .unwrap_or(false);
8037                    return Ok(Value::Boolean(has_value));
8038                }
8039            }
8040        }
8041
8042        let Some(method) = self.find_method(&class, name) else {
8043            if self.class_matches(&class, "Exception") {
8044                reject_named_args(name, &named_args)?;
8045                match name {
8046                    "message" => {
8047                        require_arity(name, args, 0)?;
8048                        return Ok(object
8049                            .borrow()
8050                            .fields
8051                            .get("message")
8052                            .cloned()
8053                            .unwrap_or(Value::Null));
8054                    }
8055                    "to_String" => {
8056                        require_arity(name, args, 0)?;
8057                        let message = object
8058                            .borrow()
8059                            .fields
8060                            .get("message")
8061                            .cloned()
8062                            .unwrap_or(Value::Null);
8063                        let message = self.render_value(&message)?;
8064                        let class_name = class.name.as_str();
8065                        if message == class_name || message.starts_with(&format!("{class_name}:")) {
8066                            return Ok(Value::String(message));
8067                        }
8068                        if message.is_empty() {
8069                            return Ok(Value::String(class.name.clone()));
8070                        }
8071                        return Ok(Value::String(format!("{}: {message}", class.name)));
8072                    }
8073                    _ => {}
8074                }
8075            }
8076            if let Some(mut builtin_value) = self.object_builtin_value(object) {
8077                if let Some(result) = stdlib::call_builtin_object_method(
8078                    self,
8079                    object,
8080                    &class.name,
8081                    &builtin_value,
8082                    name,
8083                    args,
8084                    &named_args,
8085                ) {
8086                    return result;
8087                }
8088                return self.call_method_named(&mut builtin_value, name, args, named_args);
8089            }
8090            return Err(ZuzuRustError::thrown(format!(
8091                "unsupported method '{}' for {}",
8092                name, class.name
8093            )));
8094        };
8095
8096        self.invoke_object_method_with_context(object, class, name, &method, args, named_args)
8097    }
8098
8099    fn object_set_field(
8100        &self,
8101        object: &Rc<RefCell<ObjectValue>>,
8102        field: &FieldSpec,
8103        value: Value,
8104    ) -> Result<()> {
8105        self.object_set_field_with_weak_write(object, field, value, false)
8106    }
8107
8108    fn object_set_field_with_weak_write(
8109        &self,
8110        object: &Rc<RefCell<ObjectValue>>,
8111        field: &FieldSpec,
8112        value: Value,
8113        weak_write: bool,
8114    ) -> Result<()> {
8115        let is_weak_storage = field.is_weak_storage || weak_write;
8116        if matches!(value, Value::Null) && field.declared_type.is_some() {
8117            let mut object = object.borrow_mut();
8118            if is_weak_storage {
8119                object.weak_fields.insert(field.name.clone());
8120            } else {
8121                object.weak_fields.remove(&field.name);
8122            }
8123            object.fields.insert(field.name.clone(), Value::Null);
8124            return Ok(());
8125        }
8126        self.assert_declared_type(field.declared_type.as_deref(), &value, &field.name)?;
8127        let mut object = object.borrow_mut();
8128        if is_weak_storage {
8129            object.weak_fields.insert(field.name.clone());
8130        } else {
8131            object.weak_fields.remove(&field.name);
8132        }
8133        object.fields.insert(
8134            field.name.clone(),
8135            value.stored_with_weak_policy(is_weak_storage),
8136        );
8137        Ok(())
8138    }
8139
8140    fn eval_do_expression(&self, body: &BlockStatement, env: Rc<Environment>) -> Result<Value> {
8141        let block_env = if body.needs_lexical_scope {
8142            Rc::new(Environment::new(Some(env)))
8143        } else {
8144            env
8145        };
8146        self.push_special_props_scope();
8147        let mut last = Value::Null;
8148        for statement in &body.statements {
8149            if let Some(value) =
8150                self.eval_statement_value_in_do(statement, Rc::clone(&block_env))?
8151            {
8152                last = value;
8153            }
8154            if !matches!(self.get_special_prop("__do_return__"), Value::Null) {
8155                break;
8156            }
8157        }
8158        if body.needs_lexical_scope {
8159            self.cleanup_scope(&block_env)?;
8160        }
8161        self.pop_special_props_scope();
8162        Ok(last)
8163    }
8164
8165    fn eval_statement_value_in_do(
8166        &self,
8167        statement: &Statement,
8168        env: Rc<Environment>,
8169    ) -> Result<Option<Value>> {
8170        match statement {
8171            Statement::ExpressionStatement(node) => {
8172                Ok(Some(self.eval_expression(&node.expression, env)?))
8173            }
8174            Statement::Block(block) => Ok(Some(self.eval_do_expression(block, env)?)),
8175            Statement::IfStatement(node) => {
8176                if self.value_is_truthy(&self.eval_expression(&node.test, Rc::clone(&env))?)? {
8177                    Ok(Some(self.eval_do_expression(&node.consequent, env)?))
8178                } else if let Some(alternate) = &node.alternate {
8179                    self.eval_statement_value_in_do(alternate, env)
8180                } else {
8181                    Ok(Some(Value::Null))
8182                }
8183            }
8184            other => match self.eval_statement(other, env)? {
8185                ControlFlow::Normal => Ok(None),
8186                ControlFlow::Return(value) => {
8187                    self.set_special_prop_at_level(1, "__do_return__", value.clone());
8188                    Ok(Some(value))
8189                }
8190                ControlFlow::Throw(value) => Err(ZuzuRustError::thrown(self.render_value(&value)?)),
8191                ControlFlow::Continue | ControlFlow::Break => {
8192                    Err(ZuzuRustError::runtime("loop control escaped do expression"))
8193                }
8194            },
8195        }
8196    }
8197
8198    fn eval_try_expression(
8199        &self,
8200        body: &BlockStatement,
8201        handlers: &[crate::ast::CatchClause],
8202        env: Rc<Environment>,
8203    ) -> Result<Value> {
8204        match self.eval_do_expression(body, Rc::clone(&env)) {
8205            Ok(value) => Ok(value),
8206            Err(ZuzuRustError::Thrown { value, token }) => {
8207                let thrown_value = self.lookup_thrown_value(token.as_deref());
8208                for handler in handlers {
8209                    if !self.catch_clause_matches(
8210                        handler.binding.as_ref(),
8211                        &value,
8212                        thrown_value.as_ref(),
8213                    ) {
8214                        continue;
8215                    }
8216                    let catch_env = Rc::new(Environment::new(Some(Rc::clone(&env))));
8217                    let binding_name = handler
8218                        .binding
8219                        .as_ref()
8220                        .and_then(|binding| binding.name.clone())
8221                        .unwrap_or_else(|| "e".to_owned());
8222                    let caught_value = self.make_catch_binding_value(
8223                        handler.binding.as_ref(),
8224                        &value,
8225                        thrown_value.as_ref(),
8226                    );
8227                    catch_env.define(binding_name, caught_value, true);
8228                    return self.eval_do_expression(&handler.body, catch_env);
8229                }
8230                match token {
8231                    Some(token) => Err(ZuzuRustError::thrown_with_token(value, token)),
8232                    None => Err(ZuzuRustError::thrown(value)),
8233                }
8234            }
8235            Err(err) => Err(err),
8236        }
8237    }
8238
8239    fn cleanup_scope(&self, env: &Rc<Environment>) -> Result<()> {
8240        self.cleanup_scope_preserving(env, &[])
8241    }
8242
8243    fn cleanup_scope_preserving(&self, env: &Rc<Environment>, preserved: &[&Value]) -> Result<()> {
8244        let bindings = env.bindings.borrow();
8245        let roots = bindings
8246            .values()
8247            .map(|binding| &binding.value)
8248            .collect::<Vec<_>>();
8249        let mut protected_objects = HashSet::new();
8250        let mut seen_protected_shared = HashSet::new();
8251        let mut seen_protected_objects = HashSet::new();
8252        for value in preserved {
8253            Self::collect_protected_cleanup_objects(
8254                value,
8255                &mut protected_objects,
8256                &mut seen_protected_shared,
8257                &mut seen_protected_objects,
8258            );
8259        }
8260
8261        let mut shared_refs = HashMap::new();
8262        let mut seen_shared = HashSet::new();
8263        for value in &roots {
8264            self.count_cleanup_shared_refs(value, &mut shared_refs, &mut seen_shared);
8265        }
8266
8267        let mut object_refs = HashMap::new();
8268        let mut seen_shared = HashSet::new();
8269        for value in &roots {
8270            self.count_cleanup_object_refs(value, &shared_refs, &mut object_refs, &mut seen_shared);
8271        }
8272
8273        let mut finalizers = Vec::new();
8274        let mut seen_objects = HashSet::new();
8275        let mut seen_shared = HashSet::new();
8276        for value in &roots {
8277            self.collect_cleanup_finalizers(
8278                value,
8279                &shared_refs,
8280                &object_refs,
8281                &protected_objects,
8282                &mut finalizers,
8283                &mut seen_objects,
8284                &mut seen_shared,
8285            );
8286        }
8287        drop(bindings);
8288
8289        for object in finalizers {
8290            let _ = self.call_object_method(&object, "__demolish__", &[], Vec::new())?;
8291        }
8292        Ok(())
8293    }
8294
8295    fn collect_protected_cleanup_objects(
8296        value: &Value,
8297        protected: &mut HashSet<usize>,
8298        seen_shared: &mut HashSet<usize>,
8299        seen_objects: &mut HashSet<usize>,
8300    ) {
8301        match value {
8302            Value::Object(object) => {
8303                let id = Rc::as_ptr(object) as usize;
8304                protected.insert(id);
8305                if seen_objects.insert(id) {
8306                    let fields = object.borrow();
8307                    for field in fields.fields.values() {
8308                        Self::collect_protected_cleanup_objects(
8309                            field,
8310                            protected,
8311                            seen_shared,
8312                            seen_objects,
8313                        );
8314                    }
8315                }
8316            }
8317            Value::Shared(shared) => {
8318                let id = Rc::as_ptr(shared) as usize;
8319                if seen_shared.insert(id) {
8320                    Self::collect_protected_cleanup_objects(
8321                        &shared.borrow(),
8322                        protected,
8323                        seen_shared,
8324                        seen_objects,
8325                    );
8326                }
8327            }
8328            Value::Array(values)
8329            | Value::SystemArray(values)
8330            | Value::Set(values)
8331            | Value::Bag(values) => {
8332                for value in values {
8333                    Self::collect_protected_cleanup_objects(
8334                        value,
8335                        protected,
8336                        seen_shared,
8337                        seen_objects,
8338                    );
8339                }
8340            }
8341            Value::Dict(values) | Value::SystemDict(values) => {
8342                for value in values.values() {
8343                    Self::collect_protected_cleanup_objects(
8344                        value,
8345                        protected,
8346                        seen_shared,
8347                        seen_objects,
8348                    );
8349                }
8350            }
8351            Value::PairList(values) => {
8352                for (_, value) in values {
8353                    Self::collect_protected_cleanup_objects(
8354                        value,
8355                        protected,
8356                        seen_shared,
8357                        seen_objects,
8358                    );
8359                }
8360            }
8361            Value::Pair(_, value) => {
8362                Self::collect_protected_cleanup_objects(
8363                    value,
8364                    protected,
8365                    seen_shared,
8366                    seen_objects,
8367                );
8368            }
8369            _ => {}
8370        }
8371    }
8372
8373    fn count_cleanup_shared_refs(
8374        &self,
8375        value: &Value,
8376        counts: &mut HashMap<usize, usize>,
8377        seen_shared: &mut HashSet<usize>,
8378    ) {
8379        self.walk_cleanup_value(value, counts, None, None, None, None, seen_shared);
8380    }
8381
8382    fn count_cleanup_object_refs(
8383        &self,
8384        value: &Value,
8385        shared_refs: &HashMap<usize, usize>,
8386        counts: &mut HashMap<usize, usize>,
8387        seen_shared: &mut HashSet<usize>,
8388    ) {
8389        self.walk_cleanup_value(
8390            value,
8391            counts,
8392            Some(shared_refs),
8393            None,
8394            None,
8395            None,
8396            seen_shared,
8397        );
8398    }
8399
8400    fn collect_cleanup_finalizers(
8401        &self,
8402        value: &Value,
8403        shared_refs: &HashMap<usize, usize>,
8404        object_refs: &HashMap<usize, usize>,
8405        protected_objects: &HashSet<usize>,
8406        out: &mut Vec<Rc<RefCell<ObjectValue>>>,
8407        seen_objects: &mut HashSet<usize>,
8408        seen_shared: &mut HashSet<usize>,
8409    ) {
8410        self.walk_cleanup_value(
8411            value,
8412            &mut HashMap::new(),
8413            Some(shared_refs),
8414            Some(object_refs),
8415            Some(protected_objects),
8416            Some((out, seen_objects)),
8417            seen_shared,
8418        );
8419    }
8420
8421    fn walk_cleanup_value(
8422        &self,
8423        value: &Value,
8424        counts: &mut HashMap<usize, usize>,
8425        shared_refs: Option<&HashMap<usize, usize>>,
8426        object_refs: Option<&HashMap<usize, usize>>,
8427        protected_objects: Option<&HashSet<usize>>,
8428        mut finalizers: Option<(&mut Vec<Rc<RefCell<ObjectValue>>>, &mut HashSet<usize>)>,
8429        seen_shared: &mut HashSet<usize>,
8430    ) {
8431        match value {
8432            Value::Object(object) => {
8433                let id = Rc::as_ptr(object) as usize;
8434                if let Some(object_refs) = object_refs {
8435                    if object_refs.get(&id).copied().unwrap_or(0) == Rc::strong_count(object)
8436                        && !protected_objects.is_some_and(|protected| protected.contains(&id))
8437                        && self.object_has_method(object, "__demolish__")
8438                    {
8439                        if let Some((out, seen_objects)) = finalizers.as_mut() {
8440                            if seen_objects.insert(id) {
8441                                out.push(Rc::clone(object));
8442                            }
8443                        }
8444                    }
8445                } else if shared_refs.is_some() {
8446                    *counts.entry(id).or_insert(0) += 1;
8447                }
8448            }
8449            Value::Shared(shared) => {
8450                let id = Rc::as_ptr(shared) as usize;
8451                let counting_shared_refs =
8452                    shared_refs.is_none() && object_refs.is_none() && finalizers.is_none();
8453                if counting_shared_refs {
8454                    *counts.entry(id).or_insert(0) += 1;
8455                }
8456
8457                if let Some(shared_refs) = shared_refs {
8458                    if shared_refs.get(&id).copied().unwrap_or(0) != Rc::strong_count(shared) {
8459                        return;
8460                    }
8461                }
8462
8463                if seen_shared.insert(id) {
8464                    self.walk_cleanup_value(
8465                        &shared.borrow(),
8466                        counts,
8467                        shared_refs,
8468                        object_refs,
8469                        protected_objects,
8470                        finalizers,
8471                        seen_shared,
8472                    );
8473                }
8474            }
8475            Value::Array(values)
8476            | Value::SystemArray(values)
8477            | Value::Set(values)
8478            | Value::Bag(values) => {
8479                for value in values {
8480                    self.walk_cleanup_value(
8481                        value,
8482                        counts,
8483                        shared_refs,
8484                        object_refs,
8485                        protected_objects,
8486                        finalizers
8487                            .as_mut()
8488                            .map(|(out, seen)| (&mut **out, &mut **seen)),
8489                        seen_shared,
8490                    );
8491                }
8492            }
8493            Value::Dict(values) | Value::SystemDict(values) => {
8494                for value in values.values() {
8495                    self.walk_cleanup_value(
8496                        value,
8497                        counts,
8498                        shared_refs,
8499                        object_refs,
8500                        protected_objects,
8501                        finalizers
8502                            .as_mut()
8503                            .map(|(out, seen)| (&mut **out, &mut **seen)),
8504                        seen_shared,
8505                    );
8506                }
8507            }
8508            Value::PairList(values) => {
8509                for (_, value) in values {
8510                    self.walk_cleanup_value(
8511                        value,
8512                        counts,
8513                        shared_refs,
8514                        object_refs,
8515                        protected_objects,
8516                        finalizers
8517                            .as_mut()
8518                            .map(|(out, seen)| (&mut **out, &mut **seen)),
8519                        seen_shared,
8520                    );
8521                }
8522            }
8523            Value::Pair(_, value) => {
8524                self.walk_cleanup_value(
8525                    value,
8526                    counts,
8527                    shared_refs,
8528                    object_refs,
8529                    protected_objects,
8530                    finalizers,
8531                    seen_shared,
8532                );
8533            }
8534            _ => {}
8535        }
8536    }
8537
8538    fn make_catch_binding_value(
8539        &self,
8540        binding: Option<&crate::ast::CatchBinding>,
8541        thrown_value: &str,
8542        thrown_runtime_value: Option<&Value>,
8543    ) -> Value {
8544        if let Some(value) = thrown_runtime_value {
8545            return value.clone();
8546        }
8547        let declared_type = binding.and_then(|item| item.declared_type.as_deref());
8548        match declared_type {
8549            Some("Exception")
8550            | Some("BailOutException")
8551            | Some("TypeException")
8552            | Some("CancelledException")
8553            | Some("TimeoutException")
8554            | Some("ChannelClosedException")
8555            | Some("MarshallingException")
8556            | Some("UnmarshallingException")
8557            | Some("ExhaustedException") => {
8558                let class_name = inferred_exception_class(thrown_value)
8559                    .or(declared_type)
8560                    .unwrap_or("Exception");
8561                let class_value = if class_name == "Exception" {
8562                    Value::UserClass(Rc::new(UserClassValue {
8563                        name: "Exception".to_owned(),
8564                        base: None,
8565                        traits: Vec::new(),
8566                        fields: exception_field_specs(),
8567                        methods: HashMap::new(),
8568                        static_methods: HashMap::new(),
8569                        nested_classes: HashMap::new(),
8570                        source_decl: None,
8571                        closure_env: None,
8572                    }))
8573                } else {
8574                    Value::UserClass(Rc::new(UserClassValue {
8575                        name: class_name.to_owned(),
8576                        base: Some(ClassBase::User(Rc::new(UserClassValue {
8577                            name: "Exception".to_owned(),
8578                            base: None,
8579                            traits: Vec::new(),
8580                            fields: exception_field_specs(),
8581                            methods: HashMap::new(),
8582                            static_methods: HashMap::new(),
8583                            nested_classes: HashMap::new(),
8584                            source_decl: None,
8585                            closure_env: None,
8586                        }))),
8587                        traits: Vec::new(),
8588                        fields: Vec::new(),
8589                        methods: HashMap::new(),
8590                        static_methods: HashMap::new(),
8591                        nested_classes: HashMap::new(),
8592                        source_decl: None,
8593                        closure_env: None,
8594                    }))
8595                };
8596                let mut message = thrown_value.to_owned();
8597                if let Some(stripped) = thrown_value
8598                    .strip_prefix(&format!("{class_name}: "))
8599                    .or_else(|| thrown_value.strip_prefix("Exception: "))
8600                    .or_else(|| thrown_value.strip_prefix("Bail out! "))
8601                {
8602                    message = stripped.to_owned();
8603                }
8604                match class_value {
8605                    Value::UserClass(class) => Value::Object(Rc::new(RefCell::new(ObjectValue {
8606                        class,
8607                        fields: HashMap::from([
8608                            ("message".to_owned(), Value::String(message)),
8609                            ("file".to_owned(), Value::String("<unknown>".to_owned())),
8610                            ("line".to_owned(), Value::Number(1.0)),
8611                            ("code".to_owned(), Value::Null),
8612                        ]),
8613                        weak_fields: HashSet::new(),
8614                        builtin_value: None,
8615                    }))),
8616                    _ => Value::String(thrown_value.to_owned()),
8617                }
8618            }
8619            _ => Value::String(thrown_value.to_owned()),
8620        }
8621    }
8622
8623    fn annotate_exception_metadata(&self, value: &Value, source_file: Option<&str>, line: usize) {
8624        let resolved = self.deref_value(value).unwrap_or_else(|_| value.clone());
8625        let Value::Object(object) = resolved else {
8626            return;
8627        };
8628        if !self.class_matches(&object.borrow().class, "Exception") {
8629            return;
8630        }
8631        let mut object = object.borrow_mut();
8632        if matches!(object.fields.get("file"), None | Some(Value::Null)) {
8633            let file = source_file.unwrap_or("<unknown>");
8634            object
8635                .fields
8636                .insert("file".to_owned(), Value::String(file.to_owned()));
8637        }
8638        if matches!(object.fields.get("line"), None | Some(Value::Null)) {
8639            object
8640                .fields
8641                .insert("line".to_owned(), Value::Number(line as f64));
8642        }
8643    }
8644
8645    fn normalize_die_value(
8646        &self,
8647        value: Value,
8648        source_file: Option<&str>,
8649        line: usize,
8650    ) -> Result<Value> {
8651        let resolved = self.deref_value(&value).unwrap_or_else(|_| value.clone());
8652        if let Value::Object(object) = &resolved {
8653            if self.class_matches(&object.borrow().class, "Exception") {
8654                self.annotate_exception_metadata(&value, source_file, line);
8655            }
8656            return Ok(value);
8657        }
8658
8659        let message = self.render_value(&value)?;
8660        Ok(self.make_exception_object(message, source_file, line))
8661    }
8662
8663    fn make_exception_object(
8664        &self,
8665        message: String,
8666        source_file: Option<&str>,
8667        line: usize,
8668    ) -> Value {
8669        self.make_exception_object_with_code(message, source_file, line, Value::Null)
8670    }
8671
8672    pub(in crate::runtime) fn make_exception_object_with_code(
8673        &self,
8674        message: String,
8675        source_file: Option<&str>,
8676        line: usize,
8677        code: Value,
8678    ) -> Value {
8679        Value::Object(Rc::new(RefCell::new(ObjectValue {
8680            class: Rc::new(UserClassValue {
8681                name: "Exception".to_owned(),
8682                base: None,
8683                traits: Vec::new(),
8684                fields: exception_field_specs(),
8685                methods: HashMap::new(),
8686                static_methods: HashMap::new(),
8687                nested_classes: HashMap::new(),
8688                source_decl: None,
8689                closure_env: None,
8690            }),
8691            fields: HashMap::from([
8692                ("message".to_owned(), Value::String(message)),
8693                (
8694                    "file".to_owned(),
8695                    Value::String(source_file.unwrap_or("<unknown>").to_owned()),
8696                ),
8697                ("line".to_owned(), Value::Number(line as f64)),
8698                ("code".to_owned(), code),
8699            ]),
8700            weak_fields: HashSet::new(),
8701            builtin_value: None,
8702        })))
8703    }
8704
8705    fn assert_declared_type(
8706        &self,
8707        declared_type: Option<&str>,
8708        value: &Value,
8709        name: &str,
8710    ) -> Result<()> {
8711        let declared_type = declared_type.unwrap_or("Any");
8712        if declared_type == "Any" || self.value_matches_declared_type(declared_type, value) {
8713            return Ok(());
8714        }
8715        Err(ZuzuRustError::thrown(format!(
8716            "TypeException: '{name}' must be {declared_type}, got {}",
8717            self.typeof_name(value)
8718        )))
8719    }
8720
8721    fn assert_return_type(
8722        &self,
8723        declared_type: Option<&str>,
8724        name: Option<&str>,
8725        value: &Value,
8726    ) -> Result<()> {
8727        let Some(name) = name else {
8728            return self.assert_declared_type(declared_type, value, "return value");
8729        };
8730        self.assert_declared_type(declared_type, value, &format!("return value of '{name}'"))
8731    }
8732
8733    fn value_matches_declared_type(&self, declared_type: &str, value: &Value) -> bool {
8734        let resolved = match self.normalize_value(value.clone()) {
8735            Ok(value) => value,
8736            Err(_) => return false,
8737        };
8738        match declared_type {
8739            "Any" => true,
8740            "Class" => matches!(resolved, Value::Class(_) | Value::UserClass(_)),
8741            "Number" => resolved.type_name() == "Number",
8742            "String" => resolved.type_name() == "String",
8743            "BinaryString" => resolved.type_name() == "BinaryString",
8744            "Boolean" => resolved.type_name() == "Boolean",
8745            "Null" => resolved.type_name() == "Null",
8746            "Object" => matches!(
8747                resolved,
8748                Value::Array(_)
8749                    | Value::SystemArray(_)
8750                    | Value::Set(_)
8751                    | Value::Bag(_)
8752                    | Value::Dict(_)
8753                    | Value::SystemDict(_)
8754                    | Value::Object(_)
8755            ),
8756            "Collection" => matches!(
8757                resolved,
8758                Value::Array(_)
8759                    | Value::SystemArray(_)
8760                    | Value::Set(_)
8761                    | Value::Bag(_)
8762                    | Value::Dict(_)
8763                    | Value::SystemDict(_)
8764            ),
8765            "Array" => matches!(resolved, Value::Array(_) | Value::SystemArray(_)),
8766            "Set" => matches!(resolved, Value::Set(_)),
8767            "Bag" => matches!(resolved, Value::Bag(_)),
8768            "Dict" => matches!(resolved, Value::Dict(_) | Value::SystemDict(_)),
8769            "PairList" => matches!(resolved, Value::PairList(_)),
8770            "Pair" => matches!(resolved, Value::Pair(_, _)),
8771            "Regexp" => matches!(resolved, Value::Regex(_, _)),
8772            "Function" => matches!(
8773                resolved,
8774                Value::Function(_) | Value::NativeFunction(_) | Value::Iterator(_)
8775            ),
8776            other => match &resolved {
8777                Value::Object(object) => self.class_matches(&object.borrow().class, other),
8778                Value::UserClass(class) => self.class_matches(class, other),
8779                _ => self.typeof_name(&resolved) == other,
8780            },
8781        }
8782    }
8783
8784    fn compile_regex(&self, pattern: &str, flags: &str) -> Result<Regex> {
8785        let compiled_pattern = if simple_negative_contains_regex(pattern).is_some() {
8786            "^"
8787        } else {
8788            pattern
8789        };
8790        if !self.optimizations.enables(OptimizationPass::RegexCache) {
8791            return RegexBuilder::new(compiled_pattern)
8792                .case_insensitive(flags.contains('i'))
8793                .build()
8794                .map_err(|err| ZuzuRustError::runtime(format!("invalid regexp: {err}")));
8795        }
8796        let key = (pattern.to_owned(), flags.to_owned());
8797        if let Some(regex) = self.regex_cache.borrow().get(&key) {
8798            return Ok(regex.clone());
8799        }
8800        RegexBuilder::new(compiled_pattern)
8801            .case_insensitive(flags.contains('i'))
8802            .build()
8803            .map_err(|err| ZuzuRustError::runtime(format!("invalid regexp: {err}")))
8804            .map(|regex| {
8805                self.regex_cache.borrow_mut().insert(key, regex.clone());
8806                regex
8807            })
8808    }
8809
8810    fn coerce_regex_operand(&self, regex: &Value) -> Result<(String, String)> {
8811        let regex = self.deref_value(regex)?;
8812        match &regex {
8813            Value::Regex(pattern, flags) => Ok((pattern.clone(), flags.clone())),
8814            value => Ok((self.value_to_operator_string(value)?, String::new())),
8815        }
8816    }
8817
8818    fn eval_regex_match(&self, target: &str, regex: &Value) -> Result<Value> {
8819        let (pattern, flags) = self.coerce_regex_operand(regex)?;
8820        if let Some(needle) = simple_negative_contains_regex(&pattern) {
8821            let matched = if flags.contains('i') {
8822                !target.to_lowercase().contains(&needle.to_lowercase())
8823            } else {
8824                !target.contains(needle)
8825            };
8826            return if matched {
8827                Ok(Value::Array(vec![Value::String(String::new())]))
8828            } else {
8829                Ok(Value::Boolean(false))
8830            };
8831        }
8832
8833        let compiled = self.compile_regex(&pattern, &flags)?;
8834        if flags.contains('g') {
8835            let mut all = Vec::new();
8836            for captures in compiled.captures_iter(target) {
8837                let groups = captures
8838                    .iter()
8839                    .map(|item| Value::String(item.map(|m| m.as_str()).unwrap_or("").to_owned()))
8840                    .collect();
8841                all.push(Value::Array(groups));
8842            }
8843            if all.is_empty() {
8844                Ok(Value::Boolean(false))
8845            } else {
8846                Ok(Value::Array(all))
8847            }
8848        } else if let Some(captures) = compiled.captures(target) {
8849            Ok(Value::Array(
8850                captures
8851                    .iter()
8852                    .map(|item| Value::String(item.map(|m| m.as_str()).unwrap_or("").to_owned()))
8853                    .collect(),
8854            ))
8855        } else {
8856            Ok(Value::Boolean(false))
8857        }
8858    }
8859}
8860
8861fn simple_negative_contains_regex(pattern: &str) -> Option<&str> {
8862    pattern
8863        .strip_prefix("^(?!.*")
8864        .and_then(|rest| rest.strip_suffix(')'))
8865}
8866
8867impl ReplSession<'_> {
8868    pub fn eval_source(&self, source: &str) -> Result<ReplEvalResult> {
8869        self.runtime
8870            .async_executor
8871            .enter(|| self.eval_source_inner(source))
8872    }
8873
8874    fn eval_source_inner(&self, source: &str) -> Result<ReplEvalResult> {
8875        *self.runtime.output.borrow_mut() = ExecutionOutput::default();
8876        let mut special_props = self.runtime.special_props.borrow_mut();
8877        special_props.clear();
8878        special_props.push(HashMap::new());
8879        drop(special_props);
8880        self.runtime.thrown_values.borrow_mut().clear();
8881        *self.runtime.next_thrown_id.borrow_mut() = 0;
8882        self.runtime.path_line_cursors.borrow_mut().clear();
8883
8884        let options = ParseOptions::new(
8885            false,
8886            self.runtime.infer_types,
8887            self.runtime.optimizations.clone(),
8888        );
8889        let program = parse_program_with_compile_options(source, &options)?;
8890        let value = self
8891            .runtime
8892            .eval_repl_program(&program, Rc::clone(&self.env))?;
8893        Ok(ReplEvalResult {
8894            output: self.runtime.output.borrow().clone(),
8895            value: self.runtime.render_repl_value(&value)?,
8896        })
8897    }
8898}
8899
8900impl Environment {
8901    fn new(parent: Option<Rc<Environment>>) -> Self {
8902        Self {
8903            parent,
8904            bindings: RefCell::new(HashMap::new()),
8905        }
8906    }
8907
8908    fn define(&self, name: String, value: Value, mutable: bool) {
8909        self.define_with_storage(name, value, mutable, false);
8910    }
8911
8912    fn define_with_storage(
8913        &self,
8914        name: String,
8915        value: Value,
8916        mutable: bool,
8917        is_weak_storage: bool,
8918    ) {
8919        self.bindings.borrow_mut().insert(
8920            name,
8921            Binding {
8922                value: value.stored_with_weak_policy(is_weak_storage),
8923                mutable,
8924                is_weak_storage,
8925            },
8926        );
8927    }
8928
8929    fn get(&self, name: &str) -> Result<Value> {
8930        if let Some(binding) = self.bindings.borrow().get(name) {
8931            return Ok(binding.value.clone());
8932        }
8933        if let Some(parent) = &self.parent {
8934            return parent.get(name);
8935        }
8936        Err(ZuzuRustError::runtime(format!(
8937            "use of undeclared identifier '{}'",
8938            name
8939        )))
8940    }
8941
8942    fn get_at(&self, depth: usize, name: &str) -> Result<Value> {
8943        if depth == 0 {
8944            return self
8945                .bindings
8946                .borrow()
8947                .get(name)
8948                .map(|binding| binding.value.clone())
8949                .ok_or_else(|| {
8950                    ZuzuRustError::runtime(format!("use of undeclared identifier '{}'", name))
8951                });
8952        }
8953        let Some(parent) = &self.parent else {
8954            return self.get(name);
8955        };
8956        parent.get_at(depth - 1, name)
8957    }
8958
8959    fn get_resolved(&self, depth: Option<usize>, name: &str) -> Result<Value> {
8960        match depth {
8961            Some(depth) => self.get_at(depth, name).or_else(|_| self.get(name)),
8962            None => self.get(name),
8963        }
8964    }
8965
8966    fn get_optional(&self, name: &str) -> Option<Value> {
8967        if let Some(binding) = self.bindings.borrow().get(name) {
8968            return Some(binding.value.clone());
8969        }
8970        self.parent
8971            .as_ref()
8972            .and_then(|parent| parent.get_optional(name))
8973    }
8974
8975    fn get_here(&self, name: &str) -> Option<Value> {
8976        self.bindings
8977            .borrow()
8978            .get(name)
8979            .map(|binding| binding.value.clone())
8980    }
8981
8982    fn find_binding(&self, name: &str) -> Option<Binding> {
8983        if let Some(binding) = self.bindings.borrow().get(name) {
8984            return Some(binding.clone());
8985        }
8986        self.parent
8987            .as_ref()
8988            .and_then(|parent| parent.find_binding(name))
8989    }
8990
8991    fn assign(&self, name: &str, value: Value) -> Result<()> {
8992        self.assign_with_weak_write(name, value, false)
8993    }
8994
8995    fn assign_with_weak_write(&self, name: &str, value: Value, weak_write: bool) -> Result<()> {
8996        let mut bindings = self.bindings.borrow_mut();
8997        if let Some(binding) = bindings.get_mut(name) {
8998            if !binding.mutable {
8999                return Err(ZuzuRustError::runtime(format!(
9000                    "cannot assign to immutable binding '{}'",
9001                    name
9002                )));
9003            }
9004            binding.value = value.stored_with_weak_policy(binding.is_weak_storage || weak_write);
9005            return Ok(());
9006        }
9007        drop(bindings);
9008        if let Some(parent) = &self.parent {
9009            return parent.assign_with_weak_write(name, value, weak_write);
9010        }
9011        Err(ZuzuRustError::runtime(format!(
9012            "assignment to undeclared identifier '{}'",
9013            name
9014        )))
9015    }
9016
9017    fn assign_at_with_weak_write(
9018        &self,
9019        depth: usize,
9020        name: &str,
9021        value: Value,
9022        weak_write: bool,
9023    ) -> Result<()> {
9024        if depth == 0 {
9025            let mut bindings = self.bindings.borrow_mut();
9026            if let Some(binding) = bindings.get_mut(name) {
9027                if !binding.mutable {
9028                    return Err(ZuzuRustError::runtime(format!(
9029                        "cannot assign to immutable binding '{}'",
9030                        name
9031                    )));
9032                }
9033                binding.value =
9034                    value.stored_with_weak_policy(binding.is_weak_storage || weak_write);
9035                return Ok(());
9036            }
9037            return Err(ZuzuRustError::runtime(format!(
9038                "assignment to undeclared identifier '{}'",
9039                name
9040            )));
9041        }
9042        let Some(parent) = &self.parent else {
9043            return self.assign_with_weak_write(name, value, weak_write);
9044        };
9045        parent.assign_at_with_weak_write(depth - 1, name, value, weak_write)
9046    }
9047
9048    fn assign_resolved(&self, depth: Option<usize>, name: &str, value: Value) -> Result<()> {
9049        self.assign_resolved_with_weak_write(depth, name, value, false)
9050    }
9051
9052    fn assign_resolved_with_weak_write(
9053        &self,
9054        depth: Option<usize>,
9055        name: &str,
9056        value: Value,
9057        weak_write: bool,
9058    ) -> Result<()> {
9059        match depth {
9060            Some(depth) => self
9061                .assign_at_with_weak_write(depth, name, value.clone(), weak_write)
9062                .or_else(|_| self.assign_with_weak_write(name, value, weak_write)),
9063            None => self.assign_with_weak_write(name, value, weak_write),
9064        }
9065    }
9066
9067    fn refresh_existing_binding(&self, name: &str, value: Value) -> bool {
9068        let mut bindings = self.bindings.borrow_mut();
9069        if let Some(binding) = bindings.get_mut(name) {
9070            binding.value = value.stored_with_weak_policy(binding.is_weak_storage);
9071            return true;
9072        }
9073        drop(bindings);
9074        if let Some(parent) = &self.parent {
9075            return parent.refresh_existing_binding(name, value);
9076        }
9077        false
9078    }
9079
9080    fn export_public_aliases(&self, env: Rc<Environment>) -> HashMap<String, Value> {
9081        self.bindings
9082            .borrow()
9083            .iter()
9084            .filter(|(name, _)| !name.starts_with("__"))
9085            .map(|(name, binding)| {
9086                let value = if binding.mutable {
9087                    Value::AliasRef(Rc::new(LvalueRef::Expression {
9088                        env: Rc::clone(&env),
9089                        target: Expression::Identifier {
9090                            line: 0,
9091                            source_file: None,
9092                            name: name.clone(),
9093                            inferred_type: None,
9094                            binding_depth: None,
9095                        },
9096                    }))
9097                } else {
9098                    binding.value.clone()
9099                };
9100                (name.clone(), value)
9101            })
9102            .collect()
9103    }
9104}
9105
9106impl Value {
9107    pub(in crate::runtime) fn builtin_class(name: impl Into<String>) -> Value {
9108        Value::Class(Rc::new(name.into()))
9109    }
9110
9111    pub(in crate::runtime) fn native_function(name: impl Into<String>) -> Value {
9112        Value::NativeFunction(Rc::new(name.into()))
9113    }
9114
9115    pub(in crate::runtime) fn stored_with_weak_policy(self, is_weak_storage: bool) -> Value {
9116        if is_weak_storage {
9117            let value = self
9118                .make_weak_value()
9119                .expect("weak storage conversion should not fail")
9120                .into_shared_if_composite();
9121            if value.is_weak_value() {
9122                value
9123            } else {
9124                Value::WeakStoredScalar(Box::new(value))
9125            }
9126        } else {
9127            self.into_shared_if_composite()
9128        }
9129    }
9130
9131    fn is_weak_value(&self) -> bool {
9132        matches!(
9133            self,
9134            Value::WeakFunction(_)
9135                | Value::WeakNativeFunction(_)
9136                | Value::WeakMethod(_)
9137                | Value::WeakIterator(_)
9138                | Value::WeakClass(_)
9139                | Value::WeakUserClass(_)
9140                | Value::WeakTrait(_)
9141                | Value::WeakObject(_)
9142                | Value::WeakTask(_)
9143                | Value::WeakChannel(_)
9144                | Value::WeakCancellationSource(_)
9145                | Value::WeakCancellationToken(_)
9146                | Value::WeakShared(_)
9147                | Value::WeakRef(_)
9148                | Value::WeakAliasRef(_)
9149                | Value::WeakStoredScalar(_)
9150        )
9151    }
9152
9153    fn into_shared_if_composite(self) -> Value {
9154        match self {
9155            Value::Shared(value) => Value::Shared(value),
9156            Value::Array(values) => Value::Shared(Rc::new(RefCell::new(Value::Array(
9157                values
9158                    .into_iter()
9159                    .map(Value::into_shared_if_composite)
9160                    .collect(),
9161            )))),
9162            Value::SystemArray(_) => self,
9163            Value::Set(values) => Value::Shared(Rc::new(RefCell::new(Value::Set(
9164                values
9165                    .into_iter()
9166                    .map(Value::into_shared_if_composite)
9167                    .collect(),
9168            )))),
9169            Value::Bag(values) => Value::Shared(Rc::new(RefCell::new(Value::Bag(
9170                values
9171                    .into_iter()
9172                    .map(Value::into_shared_if_composite)
9173                    .collect(),
9174            )))),
9175            Value::Dict(values) => Value::Shared(Rc::new(RefCell::new(Value::Dict(
9176                values
9177                    .into_iter()
9178                    .map(|(key, value)| (key, value.into_shared_if_composite()))
9179                    .collect(),
9180            )))),
9181            Value::SystemDict(_) => self,
9182            Value::PairList(values) => Value::Shared(Rc::new(RefCell::new(Value::PairList(
9183                values
9184                    .into_iter()
9185                    .map(|(key, value)| (key, value.into_shared_if_composite()))
9186                    .collect(),
9187            )))),
9188            Value::Pair(key, value) => Value::Shared(Rc::new(RefCell::new(Value::Pair(
9189                key,
9190                Box::new((*value).into_shared_if_composite()),
9191            )))),
9192            other => other,
9193        }
9194    }
9195
9196    fn numeric_string_value(&self) -> Option<f64> {
9197        match self {
9198            Value::String(value) => value.parse::<f64>().ok(),
9199            _ => None,
9200        }
9201    }
9202
9203    fn is_numeric_comparable(&self) -> bool {
9204        matches!(self, Value::Null | Value::Boolean(_) | Value::Number(_))
9205            || self.numeric_string_value().is_some()
9206    }
9207
9208    fn scalar_type_name(&self) -> Option<&'static str> {
9209        match self {
9210            Value::Null => Some("Null"),
9211            Value::Boolean(_) => Some("Boolean"),
9212            Value::Number(_) => Some("Number"),
9213            Value::String(_) => Some("String"),
9214            Value::BinaryString(_) => Some("BinaryString"),
9215            Value::Regex(_, _) => Some("Regexp"),
9216            Value::Shared(value) => value.borrow().scalar_type_name(),
9217            _ => None,
9218        }
9219    }
9220
9221    #[allow(dead_code)]
9222    fn is_weakable_value(&self) -> bool {
9223        if self.is_weak_value() {
9224            return true;
9225        }
9226        self.scalar_type_name().is_none()
9227    }
9228
9229    #[allow(dead_code)]
9230    fn make_weak_value(&self) -> Result<Value> {
9231        if !self.is_weakable_value() {
9232            return Ok(self.clone());
9233        }
9234        let value = self.clone().into_shared_if_composite();
9235        Ok(match value {
9236            Value::Function(value) => Value::WeakFunction(Rc::downgrade(&value)),
9237            Value::NativeFunction(value) => Value::WeakNativeFunction(Rc::downgrade(&value)),
9238            Value::Method(value) => Value::WeakMethod(Rc::downgrade(&value)),
9239            Value::Iterator(value) => Value::WeakIterator(Rc::downgrade(&value)),
9240            Value::Class(value) => Value::WeakClass(Rc::downgrade(&value)),
9241            Value::UserClass(value) => Value::WeakUserClass(Rc::downgrade(&value)),
9242            Value::Trait(value) => Value::WeakTrait(Rc::downgrade(&value)),
9243            Value::Object(value) => Value::WeakObject(Rc::downgrade(&value)),
9244            Value::Task(value) => Value::WeakTask(Rc::downgrade(&value)),
9245            Value::Channel(value) => Value::WeakChannel(Rc::downgrade(&value)),
9246            Value::CancellationSource(value) => {
9247                Value::WeakCancellationSource(Rc::downgrade(&value))
9248            }
9249            Value::CancellationToken(value) => Value::WeakCancellationToken(Rc::downgrade(&value)),
9250            Value::Shared(value) => Value::WeakShared(Rc::downgrade(&value)),
9251            Value::Ref(value) => Value::WeakRef(Rc::downgrade(&value)),
9252            Value::AliasRef(value) => Value::WeakAliasRef(Rc::downgrade(&value)),
9253            value if value.is_weak_value() => value,
9254            scalar => scalar,
9255        })
9256    }
9257
9258    #[allow(dead_code)]
9259    fn resolve_weak_value(&self) -> Value {
9260        match self {
9261            Value::WeakFunction(value) => {
9262                value.upgrade().map(Value::Function).unwrap_or(Value::Null)
9263            }
9264            Value::WeakNativeFunction(value) => value
9265                .upgrade()
9266                .map(Value::NativeFunction)
9267                .unwrap_or(Value::Null),
9268            Value::WeakMethod(value) => value.upgrade().map(Value::Method).unwrap_or(Value::Null),
9269            Value::WeakIterator(value) => {
9270                value.upgrade().map(Value::Iterator).unwrap_or(Value::Null)
9271            }
9272            Value::WeakClass(value) => value.upgrade().map(Value::Class).unwrap_or(Value::Null),
9273            Value::WeakUserClass(value) => {
9274                value.upgrade().map(Value::UserClass).unwrap_or(Value::Null)
9275            }
9276            Value::WeakTrait(value) => value.upgrade().map(Value::Trait).unwrap_or(Value::Null),
9277            Value::WeakObject(value) => value.upgrade().map(Value::Object).unwrap_or(Value::Null),
9278            Value::WeakTask(value) => value.upgrade().map(Value::Task).unwrap_or(Value::Null),
9279            Value::WeakChannel(value) => value.upgrade().map(Value::Channel).unwrap_or(Value::Null),
9280            Value::WeakCancellationSource(value) => value
9281                .upgrade()
9282                .map(Value::CancellationSource)
9283                .unwrap_or(Value::Null),
9284            Value::WeakCancellationToken(value) => value
9285                .upgrade()
9286                .map(Value::CancellationToken)
9287                .unwrap_or(Value::Null),
9288            Value::WeakShared(value) => value.upgrade().map(Value::Shared).unwrap_or(Value::Null),
9289            Value::WeakRef(value) => value.upgrade().map(Value::Ref).unwrap_or(Value::Null),
9290            Value::WeakAliasRef(value) => {
9291                value.upgrade().map(Value::AliasRef).unwrap_or(Value::Null)
9292            }
9293            Value::WeakStoredScalar(value) => (**value).clone(),
9294            value => value.clone(),
9295        }
9296    }
9297
9298    fn is_truthy(&self) -> bool {
9299        if self.is_weak_value() {
9300            return self.resolve_weak_value().is_truthy();
9301        }
9302        match self {
9303            Value::Shared(value) => value.borrow().is_truthy(),
9304            Value::Null => false,
9305            Value::Boolean(value) => *value,
9306            Value::Number(value) => *value != 0.0,
9307            Value::String(value) => !value.is_empty(),
9308            Value::BinaryString(bytes) => !bytes.is_empty(),
9309            Value::Regex(_, _) => true,
9310            Value::Array(values) | Value::SystemArray(values) => !values.is_empty(),
9311            Value::Set(values) => !values.is_empty(),
9312            Value::Bag(values) => !values.is_empty(),
9313            Value::Dict(values) | Value::SystemDict(values) => !values.is_empty(),
9314            Value::PairList(values) => !values.is_empty(),
9315            Value::Pair(_, _)
9316            | Value::Function(_)
9317            | Value::NativeFunction(_)
9318            | Value::Method(_)
9319            | Value::Iterator(_)
9320            | Value::Class(_)
9321            | Value::UserClass(_)
9322            | Value::Trait(_)
9323            | Value::Object(_)
9324            | Value::Task(_)
9325            | Value::Channel(_)
9326            | Value::CancellationSource(_)
9327            | Value::CancellationToken(_)
9328            | Value::Ref(_)
9329            | Value::AliasRef(_) => true,
9330            _ => unreachable!("weak cases handled above"),
9331        }
9332    }
9333
9334    fn to_number(&self) -> Result<f64> {
9335        if self.is_weak_value() {
9336            return self.resolve_weak_value().to_number();
9337        }
9338        match self {
9339            Value::Shared(value) => value.borrow().to_number(),
9340            Value::Null => Ok(0.0),
9341            Value::Number(value) => Ok(*value),
9342            Value::Boolean(true) => Ok(1.0),
9343            Value::Boolean(false) => Ok(0.0),
9344            Value::String(value) => {
9345                // Coercion is more permissive than the lexer: radix
9346                // prefixes and the exponent marker match either case.
9347                let trimmed = value.trim();
9348                let unsigned = trimmed.strip_prefix(['+', '-']).unwrap_or(trimmed);
9349                let radix = match unsigned.get(..2) {
9350                    Some("0x") | Some("0X") => Some(16),
9351                    Some("0b") | Some("0B") => Some(2),
9352                    Some("0o") | Some("0O") => Some(8),
9353                    _ => None,
9354                };
9355                if let Some(radix) = radix {
9356                    return u128::from_str_radix(&unsigned[2..], radix)
9357                        .map(|parsed| {
9358                            let magnitude = parsed as f64;
9359                            if trimmed.starts_with('-') {
9360                                -magnitude
9361                            } else {
9362                                magnitude
9363                            }
9364                        })
9365                        .map_err(|_| {
9366                            ZuzuRustError::runtime(format!("cannot coerce '{}' to Number", value))
9367                        });
9368                }
9369                trimmed.parse::<f64>().map_err(|_| {
9370                    ZuzuRustError::runtime(format!("cannot coerce '{}' to Number", value))
9371                })
9372            }
9373            _ => Err(ZuzuRustError::runtime("value cannot be coerced to Number")),
9374        }
9375    }
9376
9377    fn render(&self) -> String {
9378        if self.is_weak_value() {
9379            return self.resolve_weak_value().render();
9380        }
9381        match self {
9382            Value::Shared(value) => value.borrow().render(),
9383            Value::Null => "".to_owned(),
9384            Value::Boolean(true) => "true".to_owned(),
9385            Value::Boolean(false) => "false".to_owned(),
9386            Value::Number(value) => render_number(*value),
9387            Value::String(value) => value.clone(),
9388            Value::BinaryString(bytes) => String::from_utf8_lossy(bytes).into_owned(),
9389            Value::Regex(pattern, _) => pattern.clone(),
9390            Value::Array(values) | Value::SystemArray(values) => {
9391                let parts = values.iter().map(Value::render).collect::<Vec<_>>();
9392                format!("[{}]", parts.join(", "))
9393            }
9394            Value::Set(values) => {
9395                let parts = values.iter().map(Value::render).collect::<Vec<_>>();
9396                format!("<< {} >>", parts.join(", "))
9397            }
9398            Value::Bag(values) => {
9399                let parts = values.iter().map(Value::render).collect::<Vec<_>>();
9400                format!("<<< {} >>>", parts.join(", "))
9401            }
9402            Value::Dict(values) | Value::SystemDict(values) => {
9403                let mut parts = values
9404                    .iter()
9405                    .map(|(key, value)| format!("{key}: {}", value.render()))
9406                    .collect::<Vec<_>>();
9407                parts.sort();
9408                format!("{{{}}}", parts.join(", "))
9409            }
9410            Value::PairList(values) => {
9411                let parts = values
9412                    .iter()
9413                    .map(|(key, value)| format!("{key}: {}", value.render()))
9414                    .collect::<Vec<_>>();
9415                format!("{{{{{}}}}}", parts.join(", "))
9416            }
9417            Value::Pair(key, value) => format!("new Pair(pair:[\"{}\",{}])", key, value.render()),
9418            Value::Function(_) => "<Function>".to_owned(),
9419            Value::NativeFunction(name) => format!("<NativeFunction {}>", name.as_str()),
9420            Value::Method(method) => method.name.clone(),
9421            Value::Iterator(_) => "<Iterator>".to_owned(),
9422            Value::Class(name) => format!("<Class {}>", name.as_str()),
9423            Value::UserClass(class) => format!("<Class {}>", class.name),
9424            Value::Trait(trait_value) => format!("<Trait {}>", trait_value.name),
9425            Value::Object(object) => format!("<{} instance>", object.borrow().class.name),
9426            Value::Task(_) => "<Task>".to_owned(),
9427            Value::Channel(_) => "<Channel>".to_owned(),
9428            Value::CancellationSource(_) => "<CancellationSource>".to_owned(),
9429            Value::CancellationToken(_) => "<CancellationToken>".to_owned(),
9430            Value::Ref(_) | Value::AliasRef(_) => "<Ref>".to_owned(),
9431            _ => unreachable!("weak cases handled above"),
9432        }
9433    }
9434
9435    fn type_name(&self) -> &'static str {
9436        if self.is_weak_value() {
9437            return self.resolve_weak_value().type_name();
9438        }
9439        if let Some(name) = self.scalar_type_name() {
9440            return name;
9441        }
9442        match self {
9443            Value::Shared(value) => value.borrow().type_name(),
9444            Value::Array(_) | Value::SystemArray(_) => "Array",
9445            Value::Set(_) => "Set",
9446            Value::Bag(_) => "Bag",
9447            Value::Dict(_) | Value::SystemDict(_) => "Dict",
9448            Value::PairList(_) => "PairList",
9449            Value::Pair(_, _) => "Pair",
9450            Value::Method(_) => "Method",
9451            Value::Function(_) | Value::NativeFunction(_) | Value::Iterator(_) => "Function",
9452            Value::Class(_) | Value::UserClass(_) => "Class",
9453            Value::Trait(_) => "Trait",
9454            Value::Object(_) => "Object",
9455            Value::Task(_) => "Task",
9456            Value::Channel(_) => "Channel",
9457            Value::CancellationSource(_) => "CancellationSource",
9458            Value::CancellationToken(_) => "CancellationToken",
9459            Value::Ref(_) | Value::AliasRef(_) => "Ref",
9460            Value::Null
9461            | Value::Boolean(_)
9462            | Value::Number(_)
9463            | Value::String(_)
9464            | Value::BinaryString(_)
9465            | Value::Regex(_, _) => {
9466                unreachable!("scalar cases handled above")
9467            }
9468            _ => unreachable!("weak cases handled above"),
9469        }
9470    }
9471
9472    fn strict_eq(&self, other: &Value) -> bool {
9473        if self.is_weak_value() {
9474            return self.resolve_weak_value().strict_eq(other);
9475        }
9476        if other.is_weak_value() {
9477            return self.strict_eq(&other.resolve_weak_value());
9478        }
9479        match (self, other) {
9480            (Value::Shared(value), other) => return value.borrow().strict_eq(other),
9481            (this, Value::Shared(value)) => return this.strict_eq(&value.borrow()),
9482            _ => {}
9483        }
9484        match (self, other) {
9485            (Value::Null, Value::Null) => return true,
9486            (Value::Boolean(a), Value::Boolean(b)) => return a == b,
9487            (Value::Number(a), Value::Number(b)) => return a == b,
9488            (Value::String(a), Value::String(b)) => return a == b,
9489            (Value::BinaryString(a), Value::BinaryString(b)) => return a == b,
9490            _ => {}
9491        }
9492        match (self, other) {
9493            (Value::Array(a) | Value::SystemArray(a), Value::Array(b) | Value::SystemArray(b)) => {
9494                sequence_eq(a, b)
9495            }
9496            (Value::Set(a), Value::Set(b)) => collection_items_eq(a, b),
9497            (Value::Bag(a), Value::Bag(b)) => bag_items_eq(a, b),
9498            (Value::Pair(a_key, a_value), Value::Pair(b_key, b_value)) => {
9499                a_key == b_key && a_value.strict_eq(b_value)
9500            }
9501            (Value::Regex(a_pattern, a_flags), Value::Regex(b_pattern, b_flags)) => {
9502                a_pattern == b_pattern && a_flags == b_flags
9503            }
9504            (Value::Class(a), Value::Class(b)) => a == b,
9505            (Value::UserClass(a), Value::UserClass(b)) => Rc::ptr_eq(a, b),
9506            (Value::Trait(a), Value::Trait(b)) => Rc::ptr_eq(a, b),
9507            (Value::Function(a), Value::Function(b)) => Rc::ptr_eq(a, b),
9508            (Value::NativeFunction(a), Value::NativeFunction(b)) => a == b,
9509            (Value::Method(a), Value::Method(b)) => Rc::ptr_eq(a, b),
9510            (Value::Iterator(a), Value::Iterator(b)) => Rc::ptr_eq(a, b),
9511            (Value::Object(a), Value::Object(b)) => Rc::ptr_eq(a, b),
9512            (Value::Task(a), Value::Task(b)) => Rc::ptr_eq(a, b),
9513            (Value::Channel(a), Value::Channel(b)) => Rc::ptr_eq(a, b),
9514            (Value::CancellationSource(a), Value::CancellationSource(b))
9515            | (Value::CancellationToken(a), Value::CancellationToken(b))
9516            | (Value::CancellationSource(a), Value::CancellationToken(b))
9517            | (Value::CancellationToken(a), Value::CancellationSource(b)) => Rc::ptr_eq(a, b),
9518            (Value::Ref(a), Value::Ref(b))
9519            | (Value::AliasRef(a), Value::AliasRef(b))
9520            | (Value::Ref(a), Value::AliasRef(b))
9521            | (Value::AliasRef(a), Value::Ref(b)) => Rc::ptr_eq(a, b),
9522            (Value::Dict(a) | Value::SystemDict(a), Value::Dict(b) | Value::SystemDict(b)) => {
9523                dict_eq(a, b)
9524            }
9525            (Value::PairList(a), Value::PairList(b)) => pairlist_eq(a, b),
9526            _ => false,
9527        }
9528    }
9529
9530    fn coerced_eq(&self, other: &Value) -> bool {
9531        if self.is_weak_value() {
9532            return self.resolve_weak_value().coerced_eq(other);
9533        }
9534        if other.is_weak_value() {
9535            return self.coerced_eq(&other.resolve_weak_value());
9536        }
9537        match (self, other) {
9538            (Value::Shared(value), other) => return value.borrow().coerced_eq(other),
9539            (this, Value::Shared(value)) => return this.coerced_eq(&value.borrow()),
9540            _ => {}
9541        }
9542        if self.strict_eq(other) {
9543            return true;
9544        }
9545        match (self, other) {
9546            (Value::Boolean(a), Value::Number(b)) => (*a as i32 as f64) == *b,
9547            (Value::Number(a), Value::Boolean(b)) => *a == (*b as i32 as f64),
9548            _ => false,
9549        }
9550    }
9551}
9552
9553#[allow(dead_code)]
9554impl SimpleRegex {
9555    fn parse(pattern: &str, case_insensitive: bool) -> Result<Self> {
9556        let chars: Vec<char> = pattern.chars().collect();
9557        let mut index = 0usize;
9558        let parts = Self::parse_parts(&chars, &mut index, false)?;
9559        Ok(Self {
9560            parts,
9561            case_insensitive,
9562        })
9563    }
9564
9565    fn parse_parts(chars: &[char], index: &mut usize, in_group: bool) -> Result<Vec<RegexPart>> {
9566        let mut parts = Vec::new();
9567        let mut literal = String::new();
9568        while *index < chars.len() {
9569            let ch = chars[*index];
9570            if in_group && ch == ')' {
9571                break;
9572            }
9573            match ch {
9574                '(' => {
9575                    if !literal.is_empty() {
9576                        parts.push(RegexPart::Literal(std::mem::take(&mut literal)));
9577                    }
9578                    *index += 1;
9579                    let inner = Self::parse_parts(chars, index, true)?;
9580                    if *index >= chars.len() || chars[*index] != ')' {
9581                        return Err(ZuzuRustError::runtime("unsupported regexp pattern"));
9582                    }
9583                    parts.push(RegexPart::Group(inner));
9584                }
9585                '[' => {
9586                    if !literal.is_empty() {
9587                        parts.push(RegexPart::Literal(std::mem::take(&mut literal)));
9588                    }
9589                    let part = if chars.get(*index..(*index + 5))
9590                        == Some(&['[', '0', '-', '9', ']'])
9591                    {
9592                        RegexPart::DigitClassPlus
9593                    } else if chars.get(*index..(*index + 5)) == Some(&['[', 'a', '-', 'z', ']']) {
9594                        RegexPart::LowerAlphaClassPlus
9595                    } else {
9596                        return Err(ZuzuRustError::runtime("unsupported regexp character class"));
9597                    };
9598                    *index += 4;
9599                    if chars.get(*index + 1) == Some(&'+') {
9600                        *index += 1;
9601                    } else {
9602                        return Err(ZuzuRustError::runtime("unsupported regexp quantifier"));
9603                    }
9604                    parts.push(part);
9605                }
9606                ')' => break,
9607                _ => literal.push(ch),
9608            }
9609            *index += 1;
9610        }
9611        if !literal.is_empty() {
9612            parts.push(RegexPart::Literal(literal));
9613        }
9614        Ok(parts)
9615    }
9616
9617    fn find(&self, text: &str, start: usize) -> Option<RegexMatch> {
9618        let chars: Vec<char> = text.chars().collect();
9619        for offset in start..=chars.len() {
9620            let mut captures = Vec::new();
9621            if let Some(end) = self.match_parts(&self.parts, &chars, offset, &mut captures) {
9622                let full: String = chars[offset..end].iter().collect();
9623                let mut groups = vec![full];
9624                groups.extend(captures);
9625                return Some(RegexMatch {
9626                    start: offset,
9627                    end,
9628                    groups,
9629                });
9630            }
9631        }
9632        None
9633    }
9634
9635    fn match_parts(
9636        &self,
9637        parts: &[RegexPart],
9638        chars: &[char],
9639        pos: usize,
9640        captures: &mut Vec<String>,
9641    ) -> Option<usize> {
9642        if parts.is_empty() {
9643            return Some(pos);
9644        }
9645        match &parts[0] {
9646            RegexPart::Literal(text) => {
9647                let lit_chars: Vec<char> = text.chars().collect();
9648                if pos + lit_chars.len() > chars.len() {
9649                    return None;
9650                }
9651                for (offset, ch) in lit_chars.iter().enumerate() {
9652                    if !self.chars_equal(chars[pos + offset], *ch) {
9653                        return None;
9654                    }
9655                }
9656                self.match_parts(&parts[1..], chars, pos + lit_chars.len(), captures)
9657            }
9658            RegexPart::DigitClassPlus => {
9659                let mut end = pos;
9660                while end < chars.len() && chars[end].is_ascii_digit() {
9661                    end += 1;
9662                }
9663                if end == pos {
9664                    return None;
9665                }
9666                for candidate_end in (pos + 1..=end).rev() {
9667                    let mut cloned = captures.clone();
9668                    if let Some(rest_end) =
9669                        self.match_parts(&parts[1..], chars, candidate_end, &mut cloned)
9670                    {
9671                        *captures = cloned;
9672                        return Some(rest_end);
9673                    }
9674                }
9675                None
9676            }
9677            RegexPart::LowerAlphaClassPlus => {
9678                let mut end = pos;
9679                while end < chars.len() && chars[end].is_ascii_lowercase() {
9680                    end += 1;
9681                }
9682                if end == pos {
9683                    return None;
9684                }
9685                for candidate_end in (pos + 1..=end).rev() {
9686                    let mut cloned = captures.clone();
9687                    if let Some(rest_end) =
9688                        self.match_parts(&parts[1..], chars, candidate_end, &mut cloned)
9689                    {
9690                        *captures = cloned;
9691                        return Some(rest_end);
9692                    }
9693                }
9694                None
9695            }
9696            RegexPart::Group(inner) => {
9697                let mut inner_captures = captures.clone();
9698                let end = self.match_parts(inner, chars, pos, &mut inner_captures)?;
9699                let capture: String = chars[pos..end].iter().collect();
9700                inner_captures.push(capture);
9701                let rest_end = self.match_parts(&parts[1..], chars, end, &mut inner_captures)?;
9702                *captures = inner_captures;
9703                Some(rest_end)
9704            }
9705        }
9706    }
9707
9708    fn chars_equal(&self, left: char, right: char) -> bool {
9709        if self.case_insensitive {
9710            left.to_lowercase().to_string() == right.to_lowercase().to_string()
9711        } else {
9712            left == right
9713        }
9714    }
9715}
9716
9717impl fmt::Display for Value {
9718    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9719        write!(f, "{}", self.render())
9720    }
9721}
9722
9723fn is_path_operator(operator: &str) -> bool {
9724    matches!(operator, "@" | "@@" | "@?")
9725}
9726
9727fn render_number(value: f64) -> String {
9728    if value.fract() == 0.0 {
9729        if value >= i64::MIN as f64 && value <= i64::MAX as f64 {
9730            format!("{}", value as i64)
9731        } else {
9732            format!("{value:.0}")
9733        }
9734    } else {
9735        value.to_string()
9736    }
9737}
9738
9739#[cfg(test)]
9740mod weak_classification_tests {
9741    use super::*;
9742
9743    fn empty_env() -> Rc<Environment> {
9744        Rc::new(Environment {
9745            parent: None,
9746            bindings: RefCell::new(HashMap::new()),
9747        })
9748    }
9749
9750    fn empty_block() -> BlockStatement {
9751        BlockStatement {
9752            line: 0,
9753            source_file: None,
9754            statements: Vec::new(),
9755            needs_lexical_scope: false,
9756        }
9757    }
9758
9759    fn identifier_expr() -> Expression {
9760        Expression::Identifier {
9761            line: 0,
9762            source_file: None,
9763            name: "x".to_owned(),
9764            inferred_type: None,
9765            binding_depth: None,
9766        }
9767    }
9768
9769    fn method_value(env: Rc<Environment>) -> Rc<MethodValue> {
9770        Rc::new(MethodValue {
9771            name: "m".to_owned(),
9772            params: Vec::new(),
9773            return_type: None,
9774            body: empty_block(),
9775            env,
9776            is_static: false,
9777            is_async: false,
9778            is_bodyless: false,
9779            bound_receiver: None,
9780            bound_name: None,
9781        })
9782    }
9783
9784    fn user_class(env: Rc<Environment>) -> Rc<UserClassValue> {
9785        Rc::new(UserClassValue {
9786            name: "C".to_owned(),
9787            base: None,
9788            traits: Vec::new(),
9789            fields: Vec::new(),
9790            methods: HashMap::new(),
9791            static_methods: HashMap::new(),
9792            nested_classes: HashMap::new(),
9793            source_decl: None,
9794            closure_env: Some(env),
9795        })
9796    }
9797
9798    #[test]
9799    fn scalar_values_are_not_weakable() {
9800        let values = vec![
9801            Value::Null,
9802            Value::Boolean(true),
9803            Value::Number(42.0),
9804            Value::String("hello".to_owned()),
9805            Value::BinaryString(vec![1, 2, 3]),
9806            Value::Regex("x".to_owned(), "i".to_owned()),
9807            Value::Shared(Rc::new(RefCell::new(Value::String("shared".to_owned())))),
9808        ];
9809
9810        for value in values {
9811            assert!(
9812                !value.is_weakable_value(),
9813                "{} should not be weakable",
9814                value.type_name()
9815            );
9816            assert!(value.make_weak_value().is_ok());
9817            assert!(value.strict_eq(&value.resolve_weak_value()));
9818        }
9819    }
9820
9821    #[test]
9822    fn reference_capable_values_are_weakable() {
9823        let env = empty_env();
9824        let function = Rc::new(FunctionValue {
9825            name: Some("f".to_owned()),
9826            params: Vec::new(),
9827            return_type: None,
9828            body: Rc::new(RefCell::new(FunctionBody::Block(empty_block()))),
9829            env: Rc::clone(&env),
9830            is_async: false,
9831            current_method: None,
9832        });
9833        let method = method_value(Rc::clone(&env));
9834        let trait_value = Rc::new(TraitValue {
9835            name: "T".to_owned(),
9836            methods: HashMap::new(),
9837            source_decl: None,
9838            closure_env: Some(Rc::clone(&env)),
9839        });
9840        let class = user_class(Rc::clone(&env));
9841        let object = Rc::new(RefCell::new(ObjectValue {
9842            class: Rc::clone(&class),
9843            fields: HashMap::new(),
9844            weak_fields: HashSet::new(),
9845            builtin_value: None,
9846        }));
9847        let task = Rc::new(RefCell::new(TaskState {
9848            status: "pending".to_owned(),
9849            kind: TaskKind::Resolved,
9850            outcome: None,
9851        }));
9852        let channel = Rc::new(RefCell::new(ChannelState {
9853            messages: Vec::new(),
9854            closed: false,
9855        }));
9856        let cancellation = Rc::new(RefCell::new(CancellationState {
9857            cancelled: false,
9858            reason: Value::Null,
9859            watched: Vec::new(),
9860        }));
9861        let lvalue = Rc::new(LvalueRef::Expression {
9862            env: Rc::clone(&env),
9863            target: identifier_expr(),
9864        });
9865
9866        let values = vec![
9867            Value::Array(Vec::new()),
9868            Value::Set(Vec::new()),
9869            Value::Bag(Vec::new()),
9870            Value::Dict(HashMap::new()),
9871            Value::PairList(Vec::new()),
9872            Value::Pair("key".to_owned(), Box::new(Value::Null)),
9873            Value::Function(function),
9874            Value::native_function("native".to_owned()),
9875            Value::Method(method),
9876            Value::Iterator(Rc::new(RefCell::new(IteratorState {
9877                items: Vec::new(),
9878                index: 0,
9879            }))),
9880            Value::builtin_class("Builtin".to_owned()),
9881            Value::UserClass(class),
9882            Value::Trait(trait_value),
9883            Value::Object(object),
9884            Value::Task(task),
9885            Value::Channel(channel),
9886            Value::CancellationSource(Rc::clone(&cancellation)),
9887            Value::CancellationToken(cancellation),
9888            Value::Shared(Rc::new(RefCell::new(Value::Array(Vec::new())))),
9889            Value::Ref(Rc::clone(&lvalue)),
9890            Value::AliasRef(lvalue),
9891        ];
9892
9893        for value in values {
9894            assert!(
9895                value.is_weakable_value(),
9896                "{} should be weakable",
9897                value.type_name()
9898            );
9899            let weak = value.make_weak_value().expect("weak wrapping should work");
9900            assert!(
9901                weak.is_weak_value(),
9902                "{} should become weak",
9903                value.type_name()
9904            );
9905            assert_eq!(value.resolve_weak_value().type_name(), value.type_name());
9906        }
9907    }
9908
9909    #[test]
9910    fn live_weak_values_resolve_for_core_value_behaviour() {
9911        let env = empty_env();
9912        let class = user_class(Rc::clone(&env));
9913        let object = Rc::new(RefCell::new(ObjectValue {
9914            class: Rc::clone(&class),
9915            fields: HashMap::new(),
9916            weak_fields: HashSet::new(),
9917            builtin_value: None,
9918        }));
9919        let object_value = Value::Object(Rc::clone(&object));
9920        let weak_object = object_value.make_weak_value().unwrap();
9921
9922        assert!(weak_object.strict_eq(&object_value));
9923        assert_eq!(weak_object.type_name(), "Object");
9924        assert_eq!(weak_object.render(), "<C instance>");
9925        assert!(weak_object.is_truthy());
9926
9927        let class_value = Value::builtin_class("Array");
9928        let weak_class = class_value.make_weak_value().unwrap();
9929        assert!(weak_class.strict_eq(&class_value));
9930        assert_eq!(weak_class.type_name(), "Class");
9931
9932        let native_value = Value::native_function("ref_id");
9933        let weak_native = native_value.make_weak_value().unwrap();
9934        assert!(weak_native.strict_eq(&native_value));
9935        assert_eq!(weak_native.type_name(), "Function");
9936    }
9937
9938    #[test]
9939    fn dead_weak_values_resolve_to_null() {
9940        let weak_object = {
9941            let env = empty_env();
9942            let class = user_class(env);
9943            let object = Rc::new(RefCell::new(ObjectValue {
9944                class,
9945                fields: HashMap::new(),
9946                weak_fields: HashSet::new(),
9947                builtin_value: None,
9948            }));
9949            Value::Object(object).make_weak_value().unwrap()
9950        };
9951
9952        assert!(matches!(weak_object.resolve_weak_value(), Value::Null));
9953        assert_eq!(weak_object.type_name(), "Null");
9954        assert_eq!(weak_object.render(), "");
9955        assert!(!weak_object.is_truthy());
9956    }
9957
9958    #[test]
9959    fn weak_values_participate_in_collections_and_type_checks() {
9960        let runtime = Runtime::new(Vec::new());
9961        let strong_array = Value::Array(vec![Value::Number(1.0)]).into_shared_if_composite();
9962        let weak_array = strong_array.make_weak_value().unwrap();
9963
9964        assert!(Value::Array(vec![weak_array.clone()])
9965            .strict_eq(&Value::Array(vec![strong_array.clone()])));
9966        runtime
9967            .assert_declared_type(Some("Array"), &weak_array, "weak array")
9968            .unwrap();
9969        assert!(runtime.value_instanceof(&weak_array, &Value::builtin_class("Array")));
9970    }
9971
9972    #[test]
9973    fn live_weak_values_can_be_called_or_receive_methods() {
9974        let runtime = Runtime::new(Vec::new());
9975
9976        let class_value = Value::builtin_class("Array");
9977        let weak_class = class_value.make_weak_value().unwrap();
9978        let constructed = runtime
9979            .call_value(weak_class, vec![Value::Number(7.0)], Vec::new())
9980            .unwrap();
9981        assert!(constructed.strict_eq(&Value::Array(vec![Value::Number(7.0)])));
9982
9983        let env = empty_env();
9984        let class = user_class(env);
9985        let object = Value::Object(Rc::new(RefCell::new(ObjectValue {
9986            class,
9987            fields: HashMap::new(),
9988            weak_fields: HashSet::new(),
9989            builtin_value: None,
9990        })));
9991        let native_value = Value::native_function("ref_id");
9992        let weak_native = native_value.make_weak_value().unwrap();
9993        let ref_id = runtime
9994            .call_value(weak_native, vec![object], Vec::new())
9995            .unwrap();
9996        assert_eq!(ref_id.type_name(), "String");
9997
9998        let shared_array = Value::Array(vec![Value::Number(1.0)]).into_shared_if_composite();
9999        let mut weak_receiver = shared_array.make_weak_value().unwrap();
10000        let length = runtime
10001            .call_method_named(&mut weak_receiver, "length", &[], Vec::new())
10002            .unwrap();
10003        assert!(length.strict_eq(&Value::Number(1.0)));
10004    }
10005}
10006
10007fn push_unique(values: &mut Vec<Value>, value: Value) {
10008    if !values.iter().any(|existing| existing.strict_eq(&value)) {
10009        values.push(value);
10010    }
10011}
10012
10013fn exception_field_specs() -> Vec<FieldSpec> {
10014    ["message", "file", "line", "code"]
10015        .into_iter()
10016        .map(|name| FieldSpec {
10017            name: name.to_owned(),
10018            declared_type: None,
10019            mutable: true,
10020            accessors: Vec::new(),
10021            default_value: None,
10022            is_weak_storage: false,
10023        })
10024        .collect()
10025}
10026
10027fn is_builtin_exception_class(name: &str) -> bool {
10028    matches!(
10029        name,
10030        "BailOutException"
10031            | "TypeException"
10032            | "CancelledException"
10033            | "TimeoutException"
10034            | "ChannelClosedException"
10035            | "MarshallingException"
10036            | "UnmarshallingException"
10037            | "ExhaustedException"
10038            | "Exception"
10039    )
10040}
10041
10042fn inferred_exception_class(message: &str) -> Option<&'static str> {
10043    [
10044        "BailOutException",
10045        "TypeException",
10046        "CancelledException",
10047        "TimeoutException",
10048        "ChannelClosedException",
10049        "MarshallingException",
10050        "UnmarshallingException",
10051        "ExhaustedException",
10052        "Exception",
10053    ]
10054    .into_iter()
10055    .find(|class_name| {
10056        message == *class_name
10057            || message.starts_with(&format!("{class_name}:"))
10058            || (*class_name == "BailOutException" && message.starts_with("Bail out!"))
10059    })
10060}
10061
10062fn sequence_eq(left: &[Value], right: &[Value]) -> bool {
10063    left.len() == right.len()
10064        && left
10065            .iter()
10066            .zip(right.iter())
10067            .all(|(left, right)| left.strict_eq(right))
10068}
10069
10070fn collection_items_eq(left: &[Value], right: &[Value]) -> bool {
10071    left.len() == right.len()
10072        && left
10073            .iter()
10074            .all(|item| right.iter().any(|other| other.strict_eq(item)))
10075}
10076
10077fn bag_items_eq(left: &[Value], right: &[Value]) -> bool {
10078    if left.len() != right.len() {
10079        return false;
10080    }
10081    let mut used = vec![false; right.len()];
10082    for item in left {
10083        let mut matched = false;
10084        for (index, candidate) in right.iter().enumerate() {
10085            if !used[index] && candidate.strict_eq(item) {
10086                used[index] = true;
10087                matched = true;
10088                break;
10089            }
10090        }
10091        if !matched {
10092            return false;
10093        }
10094    }
10095    true
10096}
10097
10098fn resolve_index(len: usize, index: isize) -> Option<usize> {
10099    let len = len as isize;
10100    let resolved = if index < 0 { len + index } else { index };
10101    if (0..len).contains(&resolved) {
10102        Some(resolved as usize)
10103    } else {
10104        None
10105    }
10106}
10107
10108fn replace_char_range(
10109    text: &str,
10110    from: usize,
10111    to: usize,
10112    replacement: impl IntoIterator<Item = char>,
10113) -> String {
10114    let mut chars = text.chars().collect::<Vec<_>>();
10115    chars.splice(from..to, replacement);
10116    chars.into_iter().collect()
10117}
10118
10119fn dict_eq(left: &HashMap<String, Value>, right: &HashMap<String, Value>) -> bool {
10120    left.len() == right.len()
10121        && left.iter().all(|(key, value)| {
10122            right
10123                .get(key)
10124                .map(|other| other.strict_eq(value))
10125                .unwrap_or(false)
10126        })
10127}
10128
10129fn child_tasks_of(task: &Rc<RefCell<TaskState>>) -> Vec<Rc<RefCell<TaskState>>> {
10130    let state = task.borrow();
10131    match &state.kind {
10132        TaskKind::All { tasks } | TaskKind::Race { tasks } => tasks
10133            .iter()
10134            .filter_map(|value| match value {
10135                Value::Task(task) => Some(Rc::clone(task)),
10136                _ => None,
10137            })
10138            .collect(),
10139        TaskKind::Timeout {
10140            task: Value::Task(task),
10141            ..
10142        } => vec![Rc::clone(task)],
10143        TaskKind::FunctionWaiting { awaited, .. } => vec![Rc::clone(awaited)],
10144        TaskKind::SpawnWaiting { awaited, .. } => vec![Rc::clone(awaited)],
10145        _ => Vec::new(),
10146    }
10147}
10148
10149fn earliest_deadline(left: Option<Instant>, right: Option<Instant>) -> Option<Instant> {
10150    match (left, right) {
10151        (Some(left), Some(right)) => Some(left.min(right)),
10152        (Some(deadline), None) | (None, Some(deadline)) => Some(deadline),
10153        (None, None) => None,
10154    }
10155}
10156
10157async fn drive_scheduled_task(runtime: Weak<RuntimeInner>, task: Rc<RefCell<TaskState>>) {
10158    loop {
10159        let Some(inner) = runtime.upgrade() else {
10160            break;
10161        };
10162        let runtime = Runtime { inner };
10163        if task.borrow().outcome.is_some() {
10164            break;
10165        }
10166
10167        match runtime.poll_task(&task) {
10168            Ok(true) => break,
10169            Ok(false) => {}
10170            Err(err) => {
10171                let mut state = task.borrow_mut();
10172                if state.outcome.is_none() {
10173                    state.status = "rejected".to_owned();
10174                    state.outcome = Some(TaskOutcome::Rejected(err.to_string()));
10175                }
10176                break;
10177            }
10178        }
10179
10180        let deadline = runtime.next_task_deadline(&task);
10181        drop(runtime);
10182        match deadline {
10183            Some(deadline) if deadline > Instant::now() => {
10184                tokio::time::sleep_until(tokio::time::Instant::from_std(deadline)).await;
10185            }
10186            Some(_) => {
10187                tokio::task::yield_now().await;
10188            }
10189            None => {
10190                tokio::time::sleep(Duration::from_millis(1)).await;
10191            }
10192        }
10193    }
10194}
10195
10196async fn drive_native_async_task<F>(task: Rc<RefCell<TaskState>>, future: F)
10197where
10198    F: Future<Output = Result<Value>>,
10199{
10200    {
10201        let mut state = task.borrow_mut();
10202        if state.outcome.is_none() {
10203            state.status = "running".to_owned();
10204        }
10205    }
10206
10207    let result = future.await;
10208    let mut state = task.borrow_mut();
10209    if state.outcome.is_some() {
10210        return;
10211    }
10212
10213    let outcome = match result {
10214        Ok(value) => TaskOutcome::Fulfilled(value),
10215        Err(ZuzuRustError::Thrown { value, .. }) => TaskOutcome::Rejected(value),
10216        Err(err) => TaskOutcome::Rejected(err.to_string()),
10217    };
10218    state.status = match &outcome {
10219        TaskOutcome::Fulfilled(_) => "fulfilled",
10220        TaskOutcome::Rejected(_) => "rejected",
10221        TaskOutcome::Cancelled(_) => "cancelled",
10222    }
10223    .to_owned();
10224    state.outcome = Some(outcome);
10225}
10226
10227fn async_frames_of(task: &Rc<RefCell<TaskState>>) -> Option<Vec<AsyncFrame>> {
10228    let state = task.borrow();
10229    match &state.kind {
10230        TaskKind::FunctionWaiting { frames, .. } | TaskKind::SpawnWaiting { frames, .. } => {
10231            Some(frames.clone())
10232        }
10233        _ => None,
10234    }
10235}
10236
10237struct PollTaskGuard<'a> {
10238    stack: &'a RefCell<Vec<usize>>,
10239    task_id: usize,
10240}
10241
10242impl Drop for PollTaskGuard<'_> {
10243    fn drop(&mut self) {
10244        let mut stack = self.stack.borrow_mut();
10245        if stack.last() == Some(&self.task_id) {
10246            stack.pop();
10247        } else if let Some(index) = stack.iter().rposition(|id| *id == self.task_id) {
10248            stack.remove(index);
10249        }
10250    }
10251}
10252
10253impl AsyncFrame {
10254    fn statement_count(&self) -> usize {
10255        match self {
10256            AsyncFrame::Function { statements, .. }
10257            | AsyncFrame::Block { statements, .. }
10258            | AsyncFrame::Do { statements, .. } => statements.len(),
10259        }
10260    }
10261
10262    fn index(&self) -> usize {
10263        match self {
10264            AsyncFrame::Function { index, .. }
10265            | AsyncFrame::Block { index, .. }
10266            | AsyncFrame::Do { index, .. } => *index,
10267        }
10268    }
10269
10270    fn advance(&mut self) {
10271        match self {
10272            AsyncFrame::Function { index, .. }
10273            | AsyncFrame::Block { index, .. }
10274            | AsyncFrame::Do { index, .. } => {
10275                *index += 1;
10276            }
10277        }
10278    }
10279
10280    fn is_complete(&self) -> bool {
10281        self.index() >= self.statement_count()
10282    }
10283
10284    fn env(&self) -> Rc<Environment> {
10285        match self {
10286            AsyncFrame::Function { env, .. }
10287            | AsyncFrame::Block { env, .. }
10288            | AsyncFrame::Do { env, .. } => Rc::clone(env),
10289        }
10290    }
10291
10292    fn set_last(&mut self, value: Value) {
10293        if let AsyncFrame::Do { last, .. } = self {
10294            *last = value;
10295        }
10296    }
10297
10298    fn current_statement(&self) -> &Statement {
10299        match self {
10300            AsyncFrame::Function {
10301                statements, index, ..
10302            }
10303            | AsyncFrame::Block {
10304                statements, index, ..
10305            }
10306            | AsyncFrame::Do {
10307                statements, index, ..
10308            } => &statements[*index],
10309        }
10310    }
10311}