Skip to main content

ravenrs_live/
eval.rs

1//! Runs a subset of Rust read with `syn`: what small UI examples use, with the host's types
2//! reached through a [`Registry`].
3
4use std::cell::RefCell;
5use std::collections::HashMap;
6use std::fmt;
7use std::rc::Rc;
8
9use proc_macro2::Span;
10use ravenrs_reactive::State;
11use syn::punctuated::Punctuated;
12use syn::spanned::Spanned;
13use syn::{BinOp, Expr, Lit, Pat, Stmt, Token, UnOp};
14
15use crate::registry::{HostFn, Registry, use_registry};
16use crate::value::{Record, Value, short};
17
18/// Something wrong at a place of the program: its line and column (both from 1), how many
19/// characters it covers, and what is wrong.
20#[derive(Clone, Debug, PartialEq, Eq)]
21pub struct LiveError {
22    /// The line, from 1.
23    pub line: usize,
24    /// The column of the first character, from 1.
25    pub column: usize,
26    /// How many characters it covers, at least 1.
27    pub length: usize,
28    /// What is wrong.
29    pub message: String,
30}
31
32impl LiveError {
33    pub(crate) fn at(span: Span, message: impl Into<String>) -> Self {
34        let (start, end) = (span.start(), span.end());
35        let length = if end.line == start.line { end.column.saturating_sub(start.column).max(1) } else { 1 };
36        Self { line: start.line.max(1), column: start.column + 1, length, message: message.into() }
37    }
38}
39
40impl LiveError {
41    /// An error with no place in the code, such as one the host found.
42    pub fn nowhere(message: impl Into<String>) -> Self {
43        Self { line: 1, column: 1, length: 1, message: message.into() }
44    }
45}
46
47impl fmt::Display for LiveError {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        write!(f, "{}:{}: {}", self.line, self.column, self.message)
50    }
51}
52
53impl std::error::Error for LiveError {}
54
55/// How evaluation leaves an expression early.
56enum Flow {
57    Error(LiveError),
58    Return(Value),
59    Break,
60    Continue,
61}
62
63impl From<LiveError> for Flow {
64    fn from(error: LiveError) -> Self {
65        Self::Error(error)
66    }
67}
68
69type Eval<T = Value> = Result<T, Flow>;
70
71/// Variables in view, with the scope around them.
72struct Scope {
73    vars: RefCell<HashMap<String, Value>>,
74    parent: Option<Rc<Scope>>,
75}
76
77impl Scope {
78    fn root() -> Rc<Self> {
79        Rc::new(Self { vars: RefCell::new(HashMap::new()), parent: None })
80    }
81
82    fn child(parent: &Rc<Self>) -> Rc<Self> {
83        Rc::new(Self { vars: RefCell::new(HashMap::new()), parent: Some(parent.clone()) })
84    }
85
86    fn get(&self, name: &str) -> Option<Value> {
87        match self.vars.borrow().get(name) {
88            Some(value) => Some(value.clone()),
89            None => self.parent.as_ref()?.get(name),
90        }
91    }
92
93    fn set(&self, name: &str, value: Value) -> bool {
94        if let Some(slot) = self.vars.borrow_mut().get_mut(name) {
95            *slot = value;
96            return true;
97        }
98        self.parent.as_ref().is_some_and(|parent| parent.set(name, value))
99    }
100
101    fn define(&self, name: &str, value: Value) {
102        self.vars.borrow_mut().insert(name.to_owned(), value);
103    }
104}
105
106/// A function of the program: a free one, or a method of a struct it declares.
107pub(crate) struct Function {
108    sig: syn::Signature,
109    block: syn::Block,
110}
111
112/// The shape of a struct the program declares.
113#[derive(Clone)]
114enum Shape {
115    Unit,
116    Tuple(usize),
117    Named(Vec<String>),
118}
119
120/// What a whole program shares: the host, its functions, constants, structs and methods. The
121/// items written inside a function join it when that function runs.
122pub(crate) struct Program {
123    registry: Rc<Registry>,
124    functions: RefCell<HashMap<String, Rc<Function>>>,
125    constants: RefCell<HashMap<String, Rc<Expr>>>,
126    structs: RefCell<HashMap<String, Shape>>,
127    methods: RefCell<HashMap<(String, String), Rc<Function>>>,
128}
129
130impl Program {
131    pub(crate) fn method(&self, ty: &str, name: &str) -> Option<Rc<Function>> {
132        self.methods.borrow().get(&(ty.to_owned(), name.to_owned())).cloned()
133    }
134
135    fn function(&self, name: &str) -> Option<Rc<Function>> {
136        self.functions.borrow().get(name).cloned()
137    }
138
139    /// Takes in an item: a function, constant, struct or `impl` block; `use` lines are read
140    /// and left alone.
141    fn declare(&self, item: &syn::Item) -> Result<(), LiveError> {
142        match item {
143            syn::Item::Fn(function) => {
144                let made = Function { sig: function.sig.clone(), block: (*function.block).clone() };
145                self.functions.borrow_mut().insert(function.sig.ident.to_string(), Rc::new(made));
146            }
147            syn::Item::Const(constant) => {
148                self.constants
149                    .borrow_mut()
150                    .insert(constant.ident.to_string(), Rc::new((*constant.expr).clone()));
151            }
152            syn::Item::Static(constant) => {
153                self.constants
154                    .borrow_mut()
155                    .insert(constant.ident.to_string(), Rc::new((*constant.expr).clone()));
156            }
157            syn::Item::Struct(declared) => {
158                if !declared.generics.params.is_empty() {
159                    return Err(LiveError::at(
160                        declared.generics.span(),
161                        "a struct of the playground takes no generics",
162                    ));
163                }
164                let shape = match &declared.fields {
165                    syn::Fields::Unit => Shape::Unit,
166                    syn::Fields::Unnamed(fields) => Shape::Tuple(fields.unnamed.len()),
167                    syn::Fields::Named(fields) => Shape::Named(
168                        fields
169                            .named
170                            .iter()
171                            .filter_map(|f| f.ident.as_ref().map(ToString::to_string))
172                            .collect(),
173                    ),
174                };
175                self.structs.borrow_mut().insert(declared.ident.to_string(), shape);
176            }
177            syn::Item::Impl(block) => {
178                let syn::Type::Path(path) = &*block.self_ty else {
179                    return Err(LiveError::at(
180                        block.self_ty.span(),
181                        "an `impl` here is for a struct of the program",
182                    ));
183                };
184                let ty = path.path.segments.last().map(|s| s.ident.to_string()).unwrap_or_default();
185                for item in &block.items {
186                    if let syn::ImplItem::Fn(method) = item {
187                        let made = Function { sig: method.sig.clone(), block: method.block.clone() };
188                        self.methods
189                            .borrow_mut()
190                            .insert((ty.clone(), method.sig.ident.to_string()), Rc::new(made));
191                    }
192                }
193            }
194            syn::Item::Use(_) => {}
195            other => {
196                return Err(LiveError::at(
197                    other.span(),
198                    "the playground reads functions, constants, structs, `impl` blocks and `use` only",
199                ));
200            }
201        }
202        Ok(())
203    }
204}
205
206/// Calls a function of the program with these arguments; a method gets its receiver first.
207pub(crate) fn call_function(
208    program: &Rc<Program>,
209    function: &Function,
210    arguments: Vec<Value>,
211) -> Result<Value, LiveError> {
212    use_registry(program.registry.clone());
213    let runner = Runner { program: program.clone() };
214    runner.call_fn(function, arguments, function.sig.ident.span())
215}
216
217/// What a closure runs: its own code, or a function named where a closure goes, as
218/// `.map(Some)`, `Text::bound(&s, Clone::clone)` or `.validate(b, validate::email)`.
219enum Body {
220    Code(Box<Code>),
221    Path(Vec<String>),
222    Host(HostFn),
223}
224
225/// A closure written in the program: its parameters, body and the variables it sees.
226struct Code {
227    params: Vec<Pat>,
228    body: Expr,
229    scope: Rc<Scope>,
230}
231
232/// A closure of the interpreted program, callable later by the host.
233pub struct Closure {
234    body: Body,
235    program: Rc<Program>,
236    span: Span,
237}
238
239impl fmt::Debug for Closure {
240    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
241        f.debug_struct("Closure").finish_non_exhaustive()
242    }
243}
244
245impl Closure {
246    /// Calls it with these arguments.
247    pub fn call(&self, arguments: Vec<Value>) -> Result<Value, LiveError> {
248        use_registry(self.program.registry.clone());
249        let runner = Runner { program: self.program.clone() };
250        let (params, body, scope) = match &self.body {
251            Body::Code(code) => (&code.params, &code.body, &code.scope),
252            Body::Path(names) => {
253                return match runner.call_path(names, arguments, self.span) {
254                    Ok(value) | Err(Flow::Return(value)) => Ok(value),
255                    Err(flow) => Err(self.flow_error(flow)),
256                };
257            }
258            Body::Host(f) => return f(arguments).map_err(|e| self.error(e)),
259        };
260        let scope = Scope::child(scope);
261        if arguments.len() != params.len() {
262            return Err(self.error(format!(
263                "this closure takes {} arguments, and got {}",
264                params.len(),
265                arguments.len()
266            )));
267        }
268        for (pattern, value) in params.iter().zip(arguments) {
269            runner.bind(pattern, value, &scope).map_err(|flow| self.flow_error(flow))?;
270        }
271        match runner.expr(body, &scope) {
272            Ok(value) | Err(Flow::Return(value)) => Ok(value),
273            Err(flow) => Err(self.flow_error(flow)),
274        }
275    }
276
277    /// An error placed at the closure.
278    pub fn error(&self, message: impl Into<String>) -> LiveError {
279        LiveError::at(self.span, message)
280    }
281
282    fn flow_error(&self, flow: Flow) -> LiveError {
283        match flow {
284            Flow::Error(error) => error,
285            _ => self.error("break or continue outside a loop"),
286        }
287    }
288}
289
290/// Runs the function `entry` of `source`, or its first function, with no arguments.
291///
292/// ```
293/// let registry = std::rc::Rc::new(ravenrs_live::Registry::new());
294/// let value = ravenrs_live::run(
295///     "fn total() -> i64 { (1..=4).map(|n| n * n).sum() }",
296///     None,
297///     registry,
298/// )
299/// .map_err(|e| e[0].to_string())?;
300/// assert_eq!(value, ravenrs_live::Value::Int(30));
301/// # Ok::<(), String>(())
302/// ```
303pub fn run(source: &str, entry: Option<&str>, registry: Rc<Registry>) -> Result<Value, Vec<LiveError>> {
304    let file = syn::parse_file(source).map_err(|e| {
305        e.into_iter()
306            .map(|e| LiveError::at(e.span(), format!("this is not Rust the playground reads: {e}")))
307            .collect::<Vec<_>>()
308    })?;
309    let program = Rc::new(Program {
310        registry: registry.clone(),
311        functions: RefCell::default(),
312        constants: RefCell::default(),
313        structs: RefCell::default(),
314        methods: RefCell::default(),
315    });
316    let mut first = None;
317    for item in &file.items {
318        if let syn::Item::Fn(function) = item {
319            first.get_or_insert_with(|| function.sig.ident.to_string());
320        }
321        program.declare(item).map_err(|e| vec![e])?;
322    }
323    let entry = entry.map(str::to_owned).or(first).ok_or_else(|| {
324        vec![LiveError::at(
325            Span::call_site(),
326            "there is no function to run: write `fn example() -> impl View { .. }`",
327        )]
328    })?;
329    use_registry(registry);
330    let runner = Runner { program };
331    let function = runner
332        .program
333        .function(&entry)
334        .ok_or_else(|| vec![LiveError::at(Span::call_site(), format!("there is no function `{entry}`"))])?;
335    runner.call_fn(&function, Vec::new(), function.sig.ident.span()).map_err(|e| vec![e])
336}
337
338struct Runner {
339    program: Rc<Program>,
340}
341
342fn fail<T>(span: Span, message: impl Into<String>) -> Eval<T> {
343    Err(Flow::Error(LiveError::at(span, message)))
344}
345
346fn number(value: &Value) -> Option<f64> {
347    match value.read() {
348        Value::Int(n) => Some(n as f64),
349        Value::Float(n) => Some(n),
350        _ => None,
351    }
352}
353
354/// The names of a path, without the standard library's modules in front: `std::rc::Rc::new`
355/// reads as `Rc::new`.
356fn path_names(path: &syn::Path) -> Vec<String> {
357    let names: Vec<String> = path.segments.iter().map(|s| s.ident.to_string()).collect();
358    let skip = names
359        .iter()
360        .take_while(|n| {
361            matches!(
362                n.as_str(),
363                "std" | "core" | "alloc" | "collections" | "rc" | "cell" | "sync" | "f32" | "f64"
364            ) && names.len() > 2
365        })
366        .count();
367    names[skip.min(names.len().saturating_sub(2))..].to_vec()
368}
369
370impl Runner {
371    fn registry(&self) -> &Registry {
372        &self.program.registry
373    }
374
375    fn call_fn(&self, function: &Function, arguments: Vec<Value>, span: Span) -> Result<Value, LiveError> {
376        let scope = Scope::root();
377        let params: Vec<&syn::FnArg> = function.sig.inputs.iter().collect();
378        if params.len() != arguments.len() {
379            return Err(LiveError::at(
380                span,
381                format!("`{}` takes {} arguments", function.sig.ident, params.len()),
382            ));
383        }
384        for (param, value) in params.into_iter().zip(arguments) {
385            match param {
386                syn::FnArg::Typed(typed) => {
387                    self.bind(&typed.pat, value, &scope).map_err(|f| self.flow_error(f, span))?
388                }
389                syn::FnArg::Receiver(_) => scope.define("self", value),
390            }
391        }
392        match self.block(&function.block, &scope) {
393            Ok(value) | Err(Flow::Return(value)) => Ok(value),
394            Err(flow) => Err(self.flow_error(flow, span)),
395        }
396    }
397
398    fn flow_error(&self, flow: Flow, span: Span) -> LiveError {
399        match flow {
400            Flow::Error(error) => error,
401            _ => LiveError::at(span, "break or continue outside a loop"),
402        }
403    }
404
405    fn block(&self, block: &syn::Block, scope: &Rc<Scope>) -> Eval {
406        let scope = Scope::child(scope);
407        let mut last = Value::Unit;
408        for statement in &block.stmts {
409            last = match statement {
410                Stmt::Local(local) => {
411                    let value = match &local.init {
412                        Some(init) => self.expr(&init.expr, &scope)?,
413                        None => Value::Unit,
414                    };
415                    match local.init.as_ref().and_then(|init| init.diverge.as_ref()) {
416                        // `let Ok(x) = .. else { .. };`: the `else` must leave.
417                        Some((_, otherwise)) => {
418                            if !self.matches(&local.pat, &value, &scope)? {
419                                self.expr(otherwise, &scope)?;
420                                return fail(
421                                    otherwise.span(),
422                                    "the `else` of a `let` has to leave: return, break or panic",
423                                );
424                            }
425                        }
426                        None => self.bind(&local.pat, value, &scope)?,
427                    }
428                    Value::Unit
429                }
430                Stmt::Expr(expr, semicolon) => {
431                    let value = self.expr(expr, &scope)?;
432                    if semicolon.is_some() { Value::Unit } else { value }
433                }
434                Stmt::Item(item) => {
435                    match item {
436                        // Named inside a function, they are seen only there.
437                        syn::Item::Fn(function) => {
438                            let name = function.sig.ident.to_string();
439                            self.program.declare(item)?;
440                            scope.define(&name, self.path_closure(vec![name.clone()], function.span()));
441                        }
442                        syn::Item::Const(constant) => {
443                            let value = self.expr(&constant.expr, &scope)?;
444                            scope.define(&constant.ident.to_string(), value);
445                        }
446                        other => self.program.declare(other)?,
447                    }
448                    Value::Unit
449                }
450                Stmt::Macro(mac) => {
451                    let value = self.mac(&mac.mac, &scope)?;
452                    if mac.semi_token.is_some() { Value::Unit } else { value }
453                }
454            };
455        }
456        Ok(last)
457    }
458
459    /// Binds a pattern to a value, as `let` and closure parameters do.
460    fn bind(&self, pattern: &Pat, value: Value, scope: &Rc<Scope>) -> Eval<()> {
461        if self.matches(pattern, &value, scope)? {
462            Ok(())
463        } else {
464            fail(pattern.span(), format!("a {} does not fit this pattern", value.kind()))
465        }
466    }
467
468    /// Whether a value fits a pattern, binding its names when it does.
469    fn matches(&self, pattern: &Pat, value: &Value, scope: &Rc<Scope>) -> Eval<bool> {
470        Ok(match pattern {
471            Pat::Ident(ident) => {
472                let name = ident.ident.to_string();
473                // A path-like name such as `None` is a constant, not a new variable.
474                if name == "None" {
475                    return Ok(matches!(value.read(), Value::Option(None)));
476                }
477                if let Some((_, sub)) = &ident.subpat
478                    && !self.matches(sub, value, scope)?
479                {
480                    return Ok(false);
481                }
482                scope.define(&name, value.clone());
483                true
484            }
485            Pat::Wild(_) | Pat::Rest(_) => true,
486            Pat::Type(typed) => self.matches(&typed.pat, value, scope)?,
487            Pat::Reference(reference) => self.matches(&reference.pat, value, scope)?,
488            Pat::Paren(inner) => self.matches(&inner.pat, value, scope)?,
489            Pat::Tuple(tuple) => {
490                let items = match value.read() {
491                    Value::Tuple(items) => items,
492                    _ => return Ok(false),
493                };
494                if items.len() != tuple.elems.len() {
495                    return Ok(false);
496                }
497                for (pattern, item) in tuple.elems.iter().zip(items) {
498                    if !self.matches(pattern, &item, scope)? {
499                        return Ok(false);
500                    }
501                }
502                true
503            }
504            Pat::Slice(slice) => {
505                let items = value.items().map_err(|e| Flow::Error(LiveError::at(slice.span(), e)))?;
506                if items.len() != slice.elems.len() {
507                    return Ok(false);
508                }
509                for (pattern, item) in slice.elems.iter().zip(items) {
510                    if !self.matches(pattern, &item, scope)? {
511                        return Ok(false);
512                    }
513                }
514                true
515            }
516            Pat::Lit(literal) => self.literal(&literal.lit)? == value.read(),
517            Pat::Struct(pattern) => {
518                let name = path_names(&pattern.path).last().cloned().unwrap_or_default();
519                let Value::Record(record) = value.read() else { return Ok(false) };
520                if record.name != name {
521                    return Ok(false);
522                }
523                for field in &pattern.fields {
524                    let key = match &field.member {
525                        syn::Member::Named(ident) => ident.to_string(),
526                        syn::Member::Unnamed(index) => index.index.to_string(),
527                    };
528                    let Some(inner) = record.field(&key) else { return Ok(false) };
529                    if !self.matches(&field.pat, &inner, scope)? {
530                        return Ok(false);
531                    }
532                }
533                true
534            }
535            Pat::Range(range) => {
536                let Some(n) = number(value) else { return Ok(false) };
537                let low = match &range.start {
538                    Some(start) => number(&self.expr(start, scope)?).unwrap_or(f64::MIN),
539                    None => f64::MIN,
540                };
541                let high = match &range.end {
542                    Some(end) => number(&self.expr(end, scope)?).unwrap_or(f64::MAX),
543                    None => f64::MAX,
544                };
545                let closed = matches!(range.limits, syn::RangeLimits::Closed(_));
546                n >= low && (if closed { n <= high } else { n < high })
547            }
548            Pat::Or(or) => {
549                for case in &or.cases {
550                    if self.matches(case, value, scope)? {
551                        return Ok(true);
552                    }
553                }
554                false
555            }
556            Pat::TupleStruct(tuple) => {
557                let name = path_names(&tuple.path).last().cloned().unwrap_or_default();
558                let inner = match (name.as_str(), value.read()) {
559                    ("Some", Value::Option(Some(inner))) => *inner,
560                    ("Ok", Value::Result(Ok(inner))) | ("Err", Value::Result(Err(inner))) => *inner,
561                    ("Some" | "Ok" | "Err", _) => return Ok(false),
562                    (_, Value::Record(record)) if record.name == name => {
563                        let fields: Vec<Value> =
564                            record.fields.borrow().iter().map(|(_, v)| v.clone()).collect();
565                        for (pattern, field) in tuple.elems.iter().zip(fields) {
566                            if !self.matches(pattern, &field, scope)? {
567                                return Ok(false);
568                            }
569                        }
570                        return Ok(true);
571                    }
572                    _ => {
573                        return fail(
574                            tuple.span(),
575                            "only `Some(..)`, `Ok(..)`, `Err(..)` and the program's structs are read in patterns of this kind",
576                        );
577                    }
578                };
579                match tuple.elems.first() {
580                    Some(pattern) => self.matches(pattern, &inner, scope)?,
581                    None => true,
582                }
583            }
584            Pat::Path(path) => {
585                let names = path_names(&path.path);
586                let expected = self.path_value(&names, path.span())?;
587                expected == value.read() || same_host(&expected, value)
588            }
589            other => return fail(other.span(), "this pattern is not read here"),
590        })
591    }
592
593    fn literal(&self, literal: &Lit) -> Eval {
594        Ok(match literal {
595            Lit::Int(n) => {
596                if matches!(n.suffix(), "f32" | "f64") {
597                    Value::Float(
598                        n.base10_parse().map_err(|e| Flow::Error(LiveError::at(n.span(), e.to_string())))?,
599                    )
600                } else {
601                    Value::Int(
602                        n.base10_parse().map_err(|e| Flow::Error(LiveError::at(n.span(), e.to_string())))?,
603                    )
604                }
605            }
606            Lit::Float(n) => Value::Float(
607                n.base10_parse().map_err(|e| Flow::Error(LiveError::at(n.span(), e.to_string())))?,
608            ),
609            Lit::Str(s) if !s.suffix().is_empty() => return fail(s.span(), "a text literal takes no suffix"),
610            Lit::Str(s) => Value::Str(s.value()),
611            Lit::Bool(b) => Value::Bool(b.value),
612            Lit::Char(c) => Value::Char(c.value()),
613            Lit::Byte(b) => Value::Int(i64::from(b.value())),
614            other => return fail(other.span(), "this kind of literal is not read here"),
615        })
616    }
617
618    /// `Type::NAME` or a constant of the program.
619    fn path_value(&self, names: &[String], span: Span) -> Eval {
620        match names {
621            [name] => {
622                if name == "None" {
623                    return Ok(Value::Option(None));
624                }
625                let constant = self.program.constants.borrow().get(name).cloned();
626                if let Some(expr) = constant {
627                    return self.expr(&expr, &Scope::root());
628                }
629                let shape = self.program.structs.borrow().get(name).cloned();
630                match shape {
631                    Some(Shape::Unit) => return Ok(self.record(name, Vec::new())),
632                    Some(Shape::Tuple(_)) => return Ok(self.path_closure(names.to_vec(), span)),
633                    _ => {}
634                }
635                if self.program.function(name).is_some()
636                    || matches!(name.as_str(), "Some" | "Ok" | "Err")
637                    || self.registry().find_free(name).is_some()
638                {
639                    return Ok(self.path_closure(names.to_vec(), span));
640                }
641                fail(span, format!("there is no `{name}` here"))
642            }
643            [.., ty, name] => {
644                if let Some(value) = self.registry().find_constant(ty, name) {
645                    return Ok(value);
646                }
647                if let Some(value) = builtin_constant(ty, name) {
648                    return Ok(value);
649                }
650                // A function named where a closure goes, as `Clone::clone` or `validate::email`.
651                if let Some(f) = self.registry().find_function(ty, name) {
652                    return Ok(Value::Closure(Rc::new(Closure {
653                        body: Body::Host(f),
654                        program: self.program.clone(),
655                        span,
656                    })));
657                }
658                if self.program.method(ty, name).is_some()
659                    || self.registry().find_method(ty, name).is_some()
660                    || matches!(
661                        ty.as_str(),
662                        "Clone"
663                            | "ToString"
664                            | "ToOwned"
665                            | "Into"
666                            | "From"
667                            | "Vec"
668                            | "String"
669                            | "Option"
670                            | "Box"
671                            | "Rc"
672                            | "Default"
673                    )
674                {
675                    return Ok(self.path_closure(names.to_vec(), span));
676                }
677                if self.registry().knows_type(ty) {
678                    fail(span, format!("`{ty}` has no `{name}` the playground knows"))
679                } else {
680                    fail(span, format!("the playground does not know `{ty}` yet"))
681                }
682            }
683            [] => fail(span, "an empty path"),
684        }
685    }
686
687    fn path_closure(&self, names: Vec<String>, span: Span) -> Value {
688        Value::Closure(Rc::new(Closure { body: Body::Path(names), program: self.program.clone(), span }))
689    }
690
691    fn record(&self, name: &str, fields: Vec<(String, Value)>) -> Value {
692        Value::Record(Rc::new(Record {
693            name: name.to_owned(),
694            fields: RefCell::new(fields),
695            program: Some(self.program.clone()),
696        }))
697    }
698
699    /// `Name { a, b: 2, ..base }`, for a struct of the program or one the host offers.
700    fn struct_literal(&self, literal: &syn::ExprStruct, scope: &Rc<Scope>) -> Eval {
701        let names = path_names(&literal.path);
702        let name = names.last().cloned().unwrap_or_default();
703        let mut fields = Vec::new();
704        for field in &literal.fields {
705            let key = match &field.member {
706                syn::Member::Named(ident) => ident.to_string(),
707                syn::Member::Unnamed(index) => index.index.to_string(),
708            };
709            fields.push((key, self.expr(&field.expr, scope)?));
710        }
711        let base = match &literal.rest {
712            Some(rest) => Some(self.expr(rest, scope)?),
713            None => None,
714        };
715        let shape = self.program.structs.borrow().get(&name).cloned();
716        if let Some(shape) = shape {
717            let Shape::Named(order) = shape else {
718                return fail(literal.span(), format!("`{name}` has no named fields"));
719            };
720            let base = match base.map(|b| b.read()) {
721                Some(Value::Record(record)) => record.fields.borrow().clone(),
722                Some(other) => {
723                    return fail(literal.span(), format!("`..` takes a {name}, not a {}", other.kind()));
724                }
725                None => Vec::new(),
726            };
727            let mut made = Vec::new();
728            for key in order {
729                let value = match fields.iter().position(|(k, _)| *k == key) {
730                    Some(at) => fields.remove(at).1,
731                    None => match base.iter().find(|(k, _)| *k == key) {
732                        Some((_, v)) => v.clone(),
733                        None => {
734                            return fail(literal.span(), format!("the field `{key}` of `{name}` is missing"));
735                        }
736                    },
737                };
738                made.push((key, value));
739            }
740            if let Some((extra, _)) = fields.first() {
741                return fail(literal.span(), format!("`{name}` has no field `{extra}`"));
742            }
743            return Ok(self.record(&name, made));
744        }
745        match self.registry().find_record(&name) {
746            Some(build) => build(fields, base).map_err(|e| Flow::Error(LiveError::at(literal.span(), e))),
747            None => fail(
748                literal.span(),
749                format!(
750                    "the playground does not build `{}` from its fields yet",
751                    short(&quote_path(&literal.path))
752                ),
753            ),
754        }
755    }
756
757    /// `value.field`, of a tuple, a struct of the program or a host value.
758    fn field(&self, value: &Value, member: &syn::Member, span: Span) -> Eval {
759        let key = match member {
760            syn::Member::Named(ident) => ident.to_string(),
761            syn::Member::Unnamed(index) => index.index.to_string(),
762        };
763        match value.read() {
764            Value::Tuple(items) => {
765                let at: usize = key.parse().unwrap_or(usize::MAX);
766                items.get(at).cloned().ok_or(()).or_else(|()| fail(span, "the tuple is shorter"))
767            }
768            Value::Record(record) => record
769                .field(&key)
770                .ok_or(())
771                .or_else(|()| fail(span, format!("a {} has no field `{key}`", record.name))),
772            Value::Host(host) => match self.registry().find_field(host.type_name(), &key) {
773                Some(get) => get(&Value::Host(host)).map_err(|e| Flow::Error(LiveError::at(span, e))),
774                None => fail(
775                    span,
776                    format!("the playground cannot read the field `{key}` of a {}", host.type_name()),
777                ),
778            },
779            other => fail(span, format!("a {} has no fields the playground reads", other.kind())),
780        }
781    }
782
783    fn expr(&self, expr: &Expr, scope: &Rc<Scope>) -> Eval {
784        match expr {
785            Expr::Lit(literal) => self.literal(&literal.lit),
786            Expr::Path(path) => {
787                let names = path_names(&path.path);
788                if let [name] = names.as_slice()
789                    && let Some(value) = scope.get(name)
790                {
791                    return Ok(value);
792                }
793                self.path_value(&names, path.span())
794            }
795            Expr::Paren(inner) => self.expr(&inner.expr, scope),
796            Expr::Group(inner) => self.expr(&inner.expr, scope),
797            Expr::Block(block) => self.block(&block.block, scope),
798            Expr::Reference(reference) => self.expr(&reference.expr, scope),
799            Expr::Tuple(tuple) => {
800                if tuple.elems.is_empty() {
801                    return Ok(Value::Unit);
802                }
803                Ok(Value::Tuple(self.all(tuple.elems.iter(), scope)?))
804            }
805            Expr::Array(array) => Ok(Value::List(self.all(array.elems.iter(), scope)?)),
806            Expr::Repeat(repeat) => {
807                let item = self.expr(&repeat.expr, scope)?;
808                let count = self.int(&repeat.len, scope)?;
809                Ok(Value::List(vec![item; usize::try_from(count).unwrap_or(0)]))
810            }
811            Expr::Range(range) => {
812                let start = match &range.start {
813                    Some(start) => self.expr(start, scope)?.read(),
814                    None => Value::Int(0),
815                };
816                let Some(end) = &range.end else { return fail(range.span(), "a range needs an end here") };
817                let end_value = self.expr(end, scope)?.read();
818                if matches!(start, Value::Float(_)) || matches!(end_value, Value::Float(_)) {
819                    let (Some(a), Some(b)) = (number(&start), number(&end_value)) else {
820                        return fail(range.span(), "a range takes numbers");
821                    };
822                    return Ok(Value::FloatRange(a, b));
823                }
824                let (Value::Int(start), Value::Int(end)) = (start, end_value) else {
825                    return fail(range.span(), "a range takes numbers");
826                };
827                let end = if matches!(range.limits, syn::RangeLimits::Closed(_)) { end + 1 } else { end };
828                Ok(Value::Range(start, end))
829            }
830            Expr::Unary(unary) => {
831                let value = self.expr(&unary.expr, scope)?;
832                match unary.op {
833                    UnOp::Neg(_) => match value.read() {
834                        Value::Int(n) => Ok(Value::Int(-n)),
835                        Value::Float(n) => Ok(Value::Float(-n)),
836                        other => fail(unary.span(), format!("cannot negate a {}", other.kind())),
837                    },
838                    UnOp::Not(_) => match value.read() {
839                        Value::Bool(b) => Ok(Value::Bool(!b)),
840                        other => fail(unary.span(), format!("cannot negate a {}", other.kind())),
841                    },
842                    UnOp::Deref(_) => Ok(value.read()),
843                    _ => fail(unary.span(), "this operator is not read here"),
844                }
845            }
846            Expr::Binary(binary) => self.binary(binary, scope),
847            Expr::Assign(assign) => {
848                let value = self.expr(&assign.right, scope)?;
849                self.assign(&assign.left, value, scope)?;
850                Ok(Value::Unit)
851            }
852            Expr::Cast(cast) => {
853                let value = self.expr(&cast.expr, scope)?;
854                let target = match &*cast.ty {
855                    syn::Type::Path(path) => {
856                        path.path.segments.last().map(|s| s.ident.to_string()).unwrap_or_default()
857                    }
858                    _ => String::new(),
859                };
860                let as_number = number(&value);
861                Ok(match (target.as_str(), as_number, value.read()) {
862                    ("f32" | "f64", Some(n), _) => Value::Float(n),
863                    (_, Some(n), _) if target.starts_with('i') || target.starts_with('u') => {
864                        Value::Int(n as i64)
865                    }
866                    (_, _, Value::Char(c)) => Value::Int(i64::from(u32::from(c))),
867                    (_, _, Value::Bool(b)) => Value::Int(i64::from(b)),
868                    // `as AnyView` and the like only name the type; the value is the same.
869                    _ if !matches!(target.as_str(), "f32" | "f64")
870                        && !target.starts_with('i')
871                        && !target.starts_with('u') =>
872                    {
873                        value
874                    }
875                    _ => return fail(cast.span(), format!("cannot cast a {} to {target}", value.kind())),
876                })
877            }
878            Expr::If(branch) => {
879                let inner = Scope::child(scope);
880                let taken = match &*branch.cond {
881                    Expr::Let(binding) => {
882                        let value = self.expr(&binding.expr, scope)?;
883                        self.matches(&binding.pat, &value, &inner)?
884                    }
885                    condition => match self.expr(condition, scope)?.read() {
886                        Value::Bool(b) => b,
887                        other => {
888                            return fail(
889                                condition.span(),
890                                format!("a condition is a bool, not a {}", other.kind()),
891                            );
892                        }
893                    },
894                };
895                if taken {
896                    self.block(&branch.then_branch, &inner)
897                } else if let Some((_, otherwise)) = &branch.else_branch {
898                    self.expr(otherwise, scope)
899                } else {
900                    Ok(Value::Unit)
901                }
902            }
903            Expr::Match(choice) => {
904                let value = self.expr(&choice.expr, scope)?;
905                for arm in &choice.arms {
906                    let inner = Scope::child(scope);
907                    if !self.matches(&arm.pat, &value, &inner)? {
908                        continue;
909                    }
910                    if let Some((_, guard)) = &arm.guard
911                        && self.expr(guard, &inner)?.read() != Value::Bool(true)
912                    {
913                        continue;
914                    }
915                    return self.expr(&arm.body, &inner);
916                }
917                fail(choice.span(), format!("no arm fits {:?}", value))
918            }
919            Expr::ForLoop(each) => {
920                let items = self
921                    .expr(&each.expr, scope)?
922                    .items()
923                    .map_err(|e| Flow::Error(LiveError::at(each.expr.span(), e)))?;
924                for item in items {
925                    let inner = Scope::child(scope);
926                    self.bind(&each.pat, item, &inner)?;
927                    match self.block(&each.body, &inner) {
928                        Ok(_) | Err(Flow::Continue) => {}
929                        Err(Flow::Break) => break,
930                        Err(other) => return Err(other),
931                    }
932                }
933                Ok(Value::Unit)
934            }
935            Expr::While(each) => {
936                let mut rounds = 0u32;
937                loop {
938                    rounds += 1;
939                    if rounds > 100_000 {
940                        return fail(each.span(), "this loop ran 100 000 times: the playground stops it");
941                    }
942                    if self.expr(&each.cond, scope)?.read() != Value::Bool(true) {
943                        break;
944                    }
945                    match self.block(&each.body, scope) {
946                        Ok(_) | Err(Flow::Continue) => {}
947                        Err(Flow::Break) => break,
948                        Err(other) => return Err(other),
949                    }
950                }
951                Ok(Value::Unit)
952            }
953            Expr::Break(_) => Err(Flow::Break),
954            Expr::Continue(_) => Err(Flow::Continue),
955            Expr::Return(back) => {
956                let value = match &back.expr {
957                    Some(value) => self.expr(value, scope)?,
958                    None => Value::Unit,
959                };
960                Err(Flow::Return(value))
961            }
962            Expr::Closure(closure) => Ok(Value::Closure(Rc::new(Closure {
963                body: Body::Code(Box::new(Code {
964                    params: closure.inputs.iter().cloned().collect(),
965                    body: (*closure.body).clone(),
966                    scope: scope.clone(),
967                })),
968                program: self.program.clone(),
969                span: closure.span(),
970            }))),
971            Expr::Field(field) => {
972                let value = self.expr(&field.base, scope)?;
973                self.field(&value, &field.member, field.span())
974            }
975            Expr::Try(tried) => match self.expr(&tried.expr, scope)?.read() {
976                Value::Option(Some(inner)) | Value::Result(Ok(inner)) => Ok(*inner),
977                none @ (Value::Option(None) | Value::Result(Err(_))) => Err(Flow::Return(none)),
978                other => {
979                    fail(tried.span(), format!("`?` takes an Option or a Result, not a {}", other.kind()))
980                }
981            },
982            Expr::Index(index) => {
983                let items = self
984                    .expr(&index.expr, scope)?
985                    .items()
986                    .map_err(|e| Flow::Error(LiveError::at(index.span(), e)))?;
987                let at = self.int(&index.index, scope)?;
988                usize::try_from(at)
989                    .ok()
990                    .and_then(|at| items.get(at).cloned())
991                    .ok_or(())
992                    .or_else(|()| fail(index.span(), format!("index {at} is past the end ({})", items.len())))
993            }
994            Expr::Macro(mac) => self.mac(&mac.mac, scope),
995            Expr::Call(call) => self.call(call, scope),
996            Expr::MethodCall(call) => self.method(call, scope),
997            Expr::Struct(literal) => self.struct_literal(literal, scope),
998            Expr::Let(binding) => {
999                let value = self.expr(&binding.expr, scope)?;
1000                Ok(Value::Bool(self.matches(&binding.pat, &value, scope)?))
1001            }
1002            other => fail(other.span(), "this expression is not read by the playground yet"),
1003        }
1004    }
1005
1006    fn all<'a>(&self, exprs: impl Iterator<Item = &'a Expr>, scope: &Rc<Scope>) -> Eval<Vec<Value>> {
1007        exprs.map(|e| self.expr(e, scope)).collect()
1008    }
1009
1010    fn int(&self, expr: &Expr, scope: &Rc<Scope>) -> Eval<i64> {
1011        match self.expr(expr, scope)?.read() {
1012            Value::Int(n) => Ok(n),
1013            Value::Float(n) => Ok(n as i64),
1014            other => fail(expr.span(), format!("expected a number, found {}", other.kind())),
1015        }
1016    }
1017
1018    fn assign(&self, target: &Expr, value: Value, scope: &Rc<Scope>) -> Eval<()> {
1019        match target {
1020            Expr::Path(path) => {
1021                let names = path_names(&path.path);
1022                let [name] = names.as_slice() else {
1023                    return fail(path.span(), "only variables can be assigned");
1024                };
1025                match scope.get(name) {
1026                    Some(Value::Place(place)) => *place.borrow_mut() = value,
1027                    Some(_) => {
1028                        scope.set(name, value);
1029                    }
1030                    None => return fail(path.span(), format!("there is no `{name}` here")),
1031                }
1032                Ok(())
1033            }
1034            Expr::Unary(unary) if matches!(unary.op, UnOp::Deref(_)) => {
1035                match self.expr(&unary.expr, scope)? {
1036                    Value::Place(place) => {
1037                        *place.borrow_mut() = value;
1038                        Ok(())
1039                    }
1040                    other => fail(unary.span(), format!("a {} cannot be changed through `*`", other.kind())),
1041                }
1042            }
1043            Expr::Paren(inner) => self.assign(&inner.expr, value, scope),
1044            Expr::Field(field) => {
1045                let key = match &field.member {
1046                    syn::Member::Named(ident) => ident.to_string(),
1047                    syn::Member::Unnamed(index) => index.index.to_string(),
1048                };
1049                match self.expr(&field.base, scope)?.read() {
1050                    Value::Record(record) => {
1051                        let mut fields = record.fields.borrow_mut();
1052                        match fields.iter_mut().find(|(k, _)| *k == key) {
1053                            Some((_, slot)) => *slot = value,
1054                            None => {
1055                                return fail(field.span(), format!("a {} has no field `{key}`", record.name));
1056                            }
1057                        }
1058                        Ok(())
1059                    }
1060                    Value::Host(host) => match self.registry().find_set_field(host.type_name(), &key) {
1061                        Some(set) => set(&Value::Host(host), value)
1062                            .map_err(|e| Flow::Error(LiveError::at(field.span(), e))),
1063                        None => fail(
1064                            field.span(),
1065                            format!(
1066                                "the playground cannot change the field `{key}` of a {}",
1067                                host.type_name()
1068                            ),
1069                        ),
1070                    },
1071                    other => fail(field.span(), format!("a {} has no fields to change", other.kind())),
1072                }
1073            }
1074            other => fail(other.span(), "only variables, fields and `*place` can be assigned here"),
1075        }
1076    }
1077
1078    fn binary(&self, binary: &syn::ExprBinary, scope: &Rc<Scope>) -> Eval {
1079        let span = binary.span();
1080        match binary.op {
1081            BinOp::And(_) | BinOp::Or(_) => {
1082                let left = self.expr(&binary.left, scope)?.read() == Value::Bool(true);
1083                let and = matches!(binary.op, BinOp::And(_));
1084                if and != left {
1085                    return Ok(Value::Bool(left));
1086                }
1087                let right = self.expr(&binary.right, scope)?;
1088                return match right.read() {
1089                    Value::Bool(b) => Ok(Value::Bool(b)),
1090                    other => fail(span, format!("expected a bool, found {}", other.kind())),
1091                };
1092            }
1093            _ => {}
1094        }
1095        let left = self.expr(&binary.left, scope)?.read();
1096        let right = self.expr(&binary.right, scope)?.read();
1097        let compound = match binary.op {
1098            BinOp::AddAssign(_) => Some('+'),
1099            BinOp::SubAssign(_) => Some('-'),
1100            BinOp::MulAssign(_) => Some('*'),
1101            BinOp::DivAssign(_) => Some('/'),
1102            BinOp::RemAssign(_) => Some('%'),
1103            _ => None,
1104        };
1105        if let Some(op) = compound {
1106            let value = arithmetic(op, &left, &right).map_err(|e| Flow::Error(LiveError::at(span, e)))?;
1107            self.assign(&binary.left, value, scope)?;
1108            return Ok(Value::Unit);
1109        }
1110        let result = match binary.op {
1111            BinOp::Add(_) => arithmetic('+', &left, &right),
1112            BinOp::Sub(_) => arithmetic('-', &left, &right),
1113            BinOp::Mul(_) => arithmetic('*', &left, &right),
1114            BinOp::Div(_) => arithmetic('/', &left, &right),
1115            BinOp::Rem(_) => arithmetic('%', &left, &right),
1116            BinOp::Eq(_) => Ok(Value::Bool(left == right)),
1117            BinOp::Ne(_) => Ok(Value::Bool(left != right)),
1118            BinOp::Lt(_) | BinOp::Le(_) | BinOp::Gt(_) | BinOp::Ge(_) => {
1119                let order = compare(&left, &right)
1120                    .ok_or_else(|| format!("cannot compare a {} with a {}", left.kind(), right.kind()));
1121                order.map(|order| {
1122                    Value::Bool(match binary.op {
1123                        BinOp::Lt(_) => order.is_lt(),
1124                        BinOp::Le(_) => order.is_le(),
1125                        BinOp::Gt(_) => order.is_gt(),
1126                        _ => order.is_ge(),
1127                    })
1128                })
1129            }
1130            BinOp::BitAnd(_) | BinOp::BitOr(_) | BinOp::BitXor(_) => match (&left, &right) {
1131                (Value::Int(a), Value::Int(b)) => Ok(Value::Int(match binary.op {
1132                    BinOp::BitAnd(_) => a & b,
1133                    BinOp::BitOr(_) => a | b,
1134                    _ => a ^ b,
1135                })),
1136                (Value::Bool(a), Value::Bool(b)) => Ok(Value::Bool(match binary.op {
1137                    BinOp::BitAnd(_) => a & b,
1138                    BinOp::BitOr(_) => a | b,
1139                    _ => a ^ b,
1140                })),
1141                _ => Err("bit operators take integers or bools".to_owned()),
1142            },
1143            _ => Err("this operator is not read here".to_owned()),
1144        };
1145        result.map_err(|e| Flow::Error(LiveError::at(span, e)))
1146    }
1147
1148    fn mac(&self, mac: &syn::Macro, scope: &Rc<Scope>) -> Eval {
1149        let name = mac.path.segments.last().map(|s| s.ident.to_string()).unwrap_or_default();
1150        let span = mac.span();
1151        let args = || {
1152            mac.parse_body_with(Punctuated::<Expr, Token![,]>::parse_terminated)
1153                .map_err(|e| Flow::Error(LiveError::at(e.span(), e.to_string())))
1154        };
1155        match name.as_str() {
1156            "vec" => {
1157                // `vec![x; n]` or `vec![a, b, c]`.
1158                let repeat = mac.parse_body_with(|input: syn::parse::ParseStream<'_>| {
1159                    let item: Expr = input.parse()?;
1160                    input.parse::<Token![;]>()?;
1161                    let count: Expr = input.parse()?;
1162                    Ok((item, count))
1163                });
1164                if let Ok((item, count)) = repeat {
1165                    let item = self.expr(&item, scope)?;
1166                    let count = self.int(&count, scope)?;
1167                    return Ok(Value::List(vec![item; usize::try_from(count).unwrap_or(0)]));
1168                }
1169                let items = args()?;
1170                Ok(Value::List(self.all(items.iter(), scope)?))
1171            }
1172            "format" | "println" | "eprintln" | "print" | "eprint" | "panic" | "assert" | "debug_assert" => {
1173                let items: Vec<Expr> = args()?.into_iter().collect();
1174                if matches!(name.as_str(), "assert" | "debug_assert") {
1175                    let holds = match items.first() {
1176                        Some(condition) => self.expr(condition, scope)?.read() == Value::Bool(true),
1177                        None => true,
1178                    };
1179                    return if holds { Ok(Value::Unit) } else { fail(span, "an assert failed") };
1180                }
1181                let Some((first, rest)) = items.split_first() else {
1182                    if matches!(name.as_str(), "println" | "eprintln") {
1183                        crate::value::print("\n");
1184                        return Ok(Value::Unit);
1185                    }
1186                    return Ok(Value::Str(String::new()));
1187                };
1188                let Expr::Lit(syn::ExprLit { lit: Lit::Str(template), .. }) = first else {
1189                    return fail(first.span(), "format! starts with a string literal");
1190                };
1191                let values = self.all(rest.iter(), scope)?;
1192                let text = format_text(&template.value(), &values, scope)
1193                    .map_err(|e| Flow::Error(LiveError::at(template.span(), e)))?;
1194                match name.as_str() {
1195                    "format" => Ok(Value::Str(text)),
1196                    "panic" => fail(span, text),
1197                    "println" | "eprintln" => {
1198                        crate::value::print(&format!("{text}\n"));
1199                        Ok(Value::Unit)
1200                    }
1201                    _ => {
1202                        crate::value::print(&text);
1203                        Ok(Value::Unit)
1204                    }
1205                }
1206            }
1207            "unreachable" | "todo" | "unimplemented" => fail(span, format!("`{name}!` was reached")),
1208            "matches" => {
1209                let (value, pattern) = mac
1210                    .parse_body_with(|input: syn::parse::ParseStream<'_>| {
1211                        let value: Expr = input.parse()?;
1212                        input.parse::<Token![,]>()?;
1213                        let pattern = Pat::parse_multi_with_leading_vert(input)?;
1214                        Ok((value, pattern))
1215                    })
1216                    .map_err(|e| Flow::Error(LiveError::at(e.span(), e.to_string())))?;
1217                let value = self.expr(&value, scope)?;
1218                Ok(Value::Bool(self.matches(&pattern, &value, &Scope::child(scope))?))
1219            }
1220            _ => fail(span, format!("the playground does not read the macro `{name}!`")),
1221        }
1222    }
1223
1224    fn call(&self, call: &syn::ExprCall, scope: &Rc<Scope>) -> Eval {
1225        let span = call.span();
1226        let Expr::Path(path) = &*call.func else {
1227            let callee = self.expr(&call.func, scope)?;
1228            let arguments = self.all(call.args.iter(), scope)?;
1229            return self.call_value(&callee, arguments, span);
1230        };
1231        let names = path_names(&path.path);
1232        if let [name] = names.as_slice()
1233            && let Some(callee) = scope.get(name)
1234        {
1235            let arguments = self.all(call.args.iter(), scope)?;
1236            return self.call_value(&callee, arguments, span);
1237        }
1238        let arguments = self.all(call.args.iter(), scope)?;
1239        self.call_path(&names, arguments, span)
1240    }
1241
1242    /// Calls what a path names: a function of the program or of the host, a constructor the
1243    /// interpreter knows, or a method written as `Type::method(value, ..)`.
1244    fn call_path(&self, names: &[String], arguments: Vec<Value>, span: Span) -> Eval {
1245        let first = || arguments.first().cloned().unwrap_or(Value::Unit);
1246        match names.iter().map(String::as_str).collect::<Vec<_>>().as_slice() {
1247            ["Some"] => Ok(Value::Option(Some(Box::new(first())))),
1248            ["Ok"] => Ok(Value::Result(Ok(Box::new(first())))),
1249            ["Err"] => Ok(Value::Result(Err(Box::new(first())))),
1250            ["Box", "new"]
1251            | ["Rc", "new"]
1252            | ["Arc", "new"]
1253            | ["String", "from"]
1254            | ["Cell", "new"]
1255            | ["From", "from"]
1256            | ["Into", "into"] => Ok(first()),
1257            ["Vec", "new"]
1258            | ["Vec", "with_capacity"]
1259            | ["BTreeSet" | "HashSet" | "BTreeMap" | "HashMap", "new"] => Ok(Value::List(Vec::new())),
1260            ["BTreeSet" | "HashSet" | "Vec", "from" | "from_iter"] => {
1261                let mut items = first().items().map_err(|e| Flow::Error(LiveError::at(span, e)))?;
1262                if names[0].ends_with("Set") {
1263                    let mut kept: Vec<Value> = Vec::new();
1264                    for item in items.drain(..) {
1265                        if !kept.contains(&item) {
1266                            kept.push(item);
1267                        }
1268                    }
1269                    kept.sort_by(|a, b| compare(a, b).unwrap_or(std::cmp::Ordering::Equal));
1270                    items = kept;
1271                }
1272                Ok(Value::List(items))
1273            }
1274            ["f32" | "f64", "from"] => {
1275                number(&first()).map(Value::Float).ok_or(()).or_else(|()| fail(span, "a number goes here"))
1276            }
1277            [ty, "from" | "try_from"] if ty.starts_with('i') || ty.starts_with('u') => number(&first())
1278                .map(|n| Value::Int(n as i64))
1279                .ok_or(())
1280                .or_else(|()| fail(span, "a number goes here")),
1281            ["String", "new"] => Ok(Value::Str(String::new())),
1282            ["State", "new"] | ["RefCell", "new"] => Ok(Value::State(State::new(first()))),
1283            ["Default", "default"] => fail(span, "say the value instead of `Default::default()` here"),
1284            [name] => {
1285                let shape = self.program.structs.borrow().get(*name).cloned();
1286                if let Some(Shape::Tuple(count)) = shape {
1287                    if arguments.len() != count {
1288                        return fail(span, format!("`{name}` takes {count} values"));
1289                    }
1290                    let fields = arguments.into_iter().enumerate().map(|(i, v)| (i.to_string(), v)).collect();
1291                    return Ok(self.record(name, fields));
1292                }
1293                if let Some(function) = self.program.function(name) {
1294                    return self.call_fn(&function, arguments, span).map_err(Flow::Error);
1295                }
1296                if let Some(host) = self.registry().find_free(name) {
1297                    return host(arguments).map_err(|e| Flow::Error(LiveError::at(span, e)));
1298                }
1299                fail(span, format!("there is no function `{name}` here"))
1300            }
1301            [.., ty, name] => {
1302                if let Some(method) = self.program.method(ty, name) {
1303                    return self.call_fn(&method, arguments, span).map_err(Flow::Error);
1304                }
1305                if let Some(host) = self.registry().find_function(ty, name) {
1306                    return host(arguments).map_err(|e| Flow::Error(LiveError::at(span, e)));
1307                }
1308                // `Type::method(value, ..)` is `value.method(..)`, as `Clone::clone` passed to a map.
1309                let is_method = self.registry().find_method(ty, name).is_some()
1310                    || matches!(
1311                        *ty,
1312                        "Clone" | "ToString" | "ToOwned" | "Into" | "Option" | "String" | "Vec" | "str"
1313                    );
1314                if is_method && !arguments.is_empty() {
1315                    let mut arguments = arguments;
1316                    let receiver = arguments.remove(0);
1317                    return self.call_method(receiver, name, arguments, span);
1318                }
1319                if self.registry().knows_type(ty) {
1320                    fail(span, format!("`{ty}::{name}` is not one the playground knows yet"))
1321                } else {
1322                    fail(span, format!("the playground does not know `{ty}` yet"))
1323                }
1324            }
1325            [] => fail(span, "an empty path"),
1326        }
1327    }
1328
1329    fn call_value(&self, callee: &Value, arguments: Vec<Value>, span: Span) -> Eval {
1330        match callee.read() {
1331            Value::Closure(closure) => closure.call(arguments).map_err(Flow::Error),
1332            other => fail(span, format!("a {} cannot be called", other.kind())),
1333        }
1334    }
1335
1336    fn closure_arg(&self, value: &Value, span: Span) -> Eval<Rc<Closure>> {
1337        match value.read() {
1338            Value::Closure(closure) => Ok(closure),
1339            other => fail(span, format!("expected a closure, found {}", other.kind())),
1340        }
1341    }
1342
1343    fn method(&self, call: &syn::ExprMethodCall, scope: &Rc<Scope>) -> Eval {
1344        let span = call.method.span();
1345        let name = call.method.to_string();
1346        let receiver = self.expr(&call.receiver, scope)?;
1347        let arguments = self.all(call.args.iter(), scope)?;
1348        self.call_method(receiver, &name, arguments, span)
1349    }
1350
1351    fn call_method(&self, receiver: Value, name: &str, arguments: Vec<Value>, span: Span) -> Eval {
1352        let name = name.to_owned();
1353        let err = |e: String| Flow::Error(LiveError::at(span, e));
1354        // `Place`s hold what a closure may change; most methods read them.
1355        if let Value::Place(place) = &receiver
1356            && name == "push"
1357        {
1358            let mut list = place.borrow_mut();
1359            if let Value::List(items) = &mut *list {
1360                items.extend(arguments);
1361                return Ok(Value::Unit);
1362            }
1363        }
1364        let value = receiver.read();
1365        if let Value::Record(record) = &value {
1366            if let Some(method) = self.program.method(&record.name, &name) {
1367                let mut all = vec![value.clone()];
1368                all.extend(arguments);
1369                return self.call_fn(&method, all, span).map_err(Flow::Error);
1370            }
1371            if matches!(name.as_str(), "clone" | "to_owned") {
1372                let fields = record.fields.borrow().clone();
1373                return Ok(self.record(&record.name, fields));
1374            }
1375            return fail(span, format!("a {} has no method `{name}`", record.name));
1376        }
1377        if let Value::Binding(binding) = &value {
1378            return match name.as_str() {
1379                "get" => Ok(binding.get()),
1380                "set" => {
1381                    binding.set(arguments.into_iter().next().unwrap_or(Value::Unit));
1382                    Ok(Value::Unit)
1383                }
1384                "update" => {
1385                    let closure = self.closure_arg(arguments.first().unwrap_or(&Value::Unit), span)?;
1386                    let place = Rc::new(RefCell::new(fresh(binding.get())));
1387                    closure.call(vec![Value::Place(place.clone())]).map_err(Flow::Error)?;
1388                    let changed = place.borrow().clone();
1389                    binding.set(changed);
1390                    Ok(Value::Unit)
1391                }
1392                "map" => self.lens(binding.clone(), &arguments, span),
1393                "clone" | "binding" => Ok(value.clone()),
1394                _ => fail(span, format!("a Binding has no method `{name}` the playground knows")),
1395            };
1396        }
1397        if let Value::Host(host) = &value {
1398            // Methods every view has, such as `.padding(..)`, are kept under `View`.
1399            let found = self
1400                .registry()
1401                .find_method_for(host.type_name(), &name, host.held_type())
1402                .or_else(|| self.registry().find_method("View", &name));
1403            if let Some(f) = found {
1404                let mut all = vec![value.clone()];
1405                all.extend(arguments);
1406                return f(all).map_err(err);
1407            }
1408            return match name.as_str() {
1409                "clone" | "to_owned" => Ok(host.duplicate().map_or(value.clone(), Value::Host)),
1410                "into" => Ok(value),
1411                _ => {
1412                    fail(span, format!("`{}` has no method `{name}` the playground knows", host.type_name()))
1413                }
1414            };
1415        }
1416        if let Value::State(state) = &value {
1417            return match name.as_str() {
1418                "get" => Ok(state.get()),
1419                "set" | "set_if_changed" => {
1420                    state.set(arguments.into_iter().next().unwrap_or(Value::Unit));
1421                    Ok(Value::Unit)
1422                }
1423                "update" => {
1424                    let closure = self.closure_arg(arguments.first().unwrap_or(&Value::Unit), span)?;
1425                    let place = Rc::new(RefCell::new(fresh(state.get())));
1426                    closure.call(vec![Value::Place(place.clone())]).map_err(Flow::Error)?;
1427                    let changed = place.borrow().clone();
1428                    state.set(changed);
1429                    Ok(Value::Unit)
1430                }
1431                "with" => {
1432                    let closure = self.closure_arg(arguments.first().unwrap_or(&Value::Unit), span)?;
1433                    closure.call(vec![state.get()]).map_err(Flow::Error)
1434                }
1435                "map" => self.lens(state.binding(), &arguments, span),
1436                "clone" | "binding" => Ok(value),
1437                _ => fail(span, format!("a State has no method `{name}` the playground knows")),
1438            };
1439        }
1440        builtin_method(self, &name, value, arguments, span)
1441    }
1442}
1443
1444/// A copy of a value whose host objects are copied too, so changing it through a place does
1445/// not change the original before it is set back.
1446fn fresh(value: Value) -> Value {
1447    match value {
1448        Value::Host(host) => Value::Host(host.duplicate().unwrap_or(host)),
1449        Value::Tuple(items) => Value::Tuple(items.into_iter().map(fresh).collect()),
1450        Value::List(items) => Value::List(items.into_iter().map(fresh).collect()),
1451        Value::Option(Some(inner)) => Value::Option(Some(Box::new(fresh(*inner)))),
1452        other => other,
1453    }
1454}
1455
1456impl Runner {
1457    /// `binding.map(|whole| part, |whole, part| ..)`: a binding to a part of another.
1458    fn lens(&self, whole: ravenrs_reactive::Binding<Value>, arguments: &[Value], span: Span) -> Eval {
1459        let get = self.closure_arg(arguments.first().unwrap_or(&Value::Unit), span)?;
1460        let set = self.closure_arg(arguments.get(1).unwrap_or(&Value::Unit), span)?;
1461        let reader = whole.clone();
1462        let binding = ravenrs_reactive::Binding::new(
1463            move || match get.call(vec![reader.get()]) {
1464                Ok(part) => part,
1465                Err(problem) => {
1466                    crate::value::report(problem);
1467                    Value::Unit
1468                }
1469            },
1470            move |part: Value| {
1471                let place = Rc::new(RefCell::new(fresh(whole.get())));
1472                match set.call(vec![Value::Place(place.clone()), part]) {
1473                    Ok(_) => whole.set(place.borrow().clone()),
1474                    Err(problem) => crate::value::report(problem),
1475                }
1476            },
1477        );
1478        Ok(Value::Binding(binding))
1479    }
1480}
1481
1482fn quote_path(path: &syn::Path) -> String {
1483    path_names(path).join("::")
1484}
1485
1486fn same_host(expected: &Value, value: &Value) -> bool {
1487    match (expected, value.read()) {
1488        (Value::Host(a), Value::Host(b)) => {
1489            a.type_name() == b.type_name() && format!("{a:?}") == format!("{b:?}")
1490        }
1491        _ => false,
1492    }
1493}
1494
1495impl fmt::Debug for crate::value::Host {
1496    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1497        write!(f, "<{}>", self.type_name())
1498    }
1499}
1500
1501fn builtin_constant(ty: &str, name: &str) -> Option<Value> {
1502    Some(match (ty, name) {
1503        ("f32" | "f64", "MAX") => Value::Float(f64::MAX),
1504        ("f32" | "f64", "MIN") => Value::Float(f64::MIN),
1505        ("f32" | "f64", "INFINITY") => Value::Float(f64::INFINITY),
1506        ("f32" | "f64", "NEG_INFINITY") => Value::Float(f64::NEG_INFINITY),
1507        ("f32", "EPSILON") => Value::Float(f64::from(f32::EPSILON)),
1508        ("consts", "PI") => Value::Float(std::f64::consts::PI),
1509        ("consts", "TAU") => Value::Float(std::f64::consts::TAU),
1510        ("u8", "MAX") => Value::Int(i64::from(u8::MAX)),
1511        ("u32", "MAX") => Value::Int(i64::from(u32::MAX)),
1512        ("i32", "MAX") => Value::Int(i64::from(i32::MAX)),
1513        ("usize" | "u64" | "i64", "MAX") => Value::Int(i64::MAX),
1514        _ => return None,
1515    })
1516}
1517
1518fn arithmetic(op: char, left: &Value, right: &Value) -> Result<Value, String> {
1519    match (left, right) {
1520        (Value::Int(a), Value::Int(b)) => Ok(Value::Int(match op {
1521            '+' => a.wrapping_add(*b),
1522            '-' => a.wrapping_sub(*b),
1523            '*' => a.wrapping_mul(*b),
1524            '/' if *b == 0 => return Err("division by zero".into()),
1525            '/' => a / b,
1526            '%' if *b == 0 => return Err("division by zero".into()),
1527            _ => a % b,
1528        })),
1529        (Value::Str(a), Value::Str(b)) if op == '+' => Ok(Value::Str(format!("{a}{b}"))),
1530        (Value::Str(a), Value::Char(b)) if op == '+' => Ok(Value::Str(format!("{a}{b}"))),
1531        _ => match (number(left), number(right)) {
1532            (Some(a), Some(b)) => Ok(Value::Float(match op {
1533                '+' => a + b,
1534                '-' => a - b,
1535                '*' => a * b,
1536                '/' => a / b,
1537                _ => a % b,
1538            })),
1539            _ => Err(format!("cannot use `{op}` on a {} and a {}", left.kind(), right.kind())),
1540        },
1541    }
1542}
1543
1544fn compare(left: &Value, right: &Value) -> Option<std::cmp::Ordering> {
1545    match (left, right) {
1546        (Value::Str(a), Value::Str(b)) => Some(a.cmp(b)),
1547        (Value::Char(a), Value::Char(b)) => Some(a.cmp(b)),
1548        (Value::Bool(a), Value::Bool(b)) => Some(a.cmp(b)),
1549        (Value::Tuple(a), Value::Tuple(b)) | (Value::List(a), Value::List(b)) => {
1550            for (x, y) in a.iter().zip(b) {
1551                match compare(x, y)? {
1552                    std::cmp::Ordering::Equal => {}
1553                    other => return Some(other),
1554                }
1555            }
1556            Some(a.len().cmp(&b.len()))
1557        }
1558        _ => number(left)?.partial_cmp(&number(right)?),
1559    }
1560}
1561
1562/// How a value is written by `{}`.
1563fn display(value: &Value) -> String {
1564    match value.read() {
1565        Value::Str(s) => s,
1566        Value::Int(n) => n.to_string(),
1567        Value::Float(n) => n.to_string(),
1568        Value::Char(c) => c.to_string(),
1569        Value::Bool(b) => b.to_string(),
1570        other => format!("{other:?}"),
1571    }
1572}
1573
1574/// `format!`'s rules for `{}`, `{:?}`, `{name}`, `{0}`, `{:.2}`, `{:>5}` and `{{`.
1575fn format_text(template: &str, values: &[Value], scope: &Rc<Scope>) -> Result<String, String> {
1576    let mut out = String::new();
1577    let mut next = 0;
1578    let mut chars = template.chars().peekable();
1579    while let Some(c) = chars.next() {
1580        match c {
1581            '{' if chars.peek() == Some(&'{') => {
1582                chars.next();
1583                out.push('{');
1584            }
1585            '}' if chars.peek() == Some(&'}') => {
1586                chars.next();
1587                out.push('}');
1588            }
1589            '{' => {
1590                let mut inside = String::new();
1591                for c in chars.by_ref() {
1592                    if c == '}' {
1593                        break;
1594                    }
1595                    inside.push(c);
1596                }
1597                let (name, spec) = inside.split_once(':').unwrap_or((&inside, ""));
1598                let value = if name.is_empty() {
1599                    next += 1;
1600                    values.get(next - 1).cloned().ok_or("more {} than values")?
1601                } else if let Ok(index) = name.parse::<usize>() {
1602                    values.get(index).cloned().ok_or("no value at that position")?
1603                } else {
1604                    scope.get(name).ok_or_else(|| format!("there is no `{name}` here"))?
1605                };
1606                out.push_str(&formatted(&value, spec));
1607            }
1608            other => out.push(other),
1609        }
1610    }
1611    Ok(out)
1612}
1613
1614fn formatted(value: &Value, spec: &str) -> String {
1615    let debug = spec.ends_with('?');
1616    let spec = spec.trim_end_matches('?');
1617    let (head, precision) = match spec.split_once('.') {
1618        Some((head, digits)) => (head, digits.parse::<usize>().ok()),
1619        None => (spec, None),
1620    };
1621    let mut text = match (precision, number(value)) {
1622        (Some(places), Some(n)) => format!("{n:.places$}"),
1623        _ if debug => format!("{:?}", value.read()),
1624        _ => display(value),
1625    };
1626    let (align, width) = match head.chars().next() {
1627        Some(a @ ('<' | '>' | '^')) => (Some(a), head[1..].trim_start_matches('0').parse::<usize>().ok()),
1628        _ => (None, head.trim_start_matches('0').parse::<usize>().ok()),
1629    };
1630    if let Some(width) = width {
1631        let pad = width.saturating_sub(text.chars().count());
1632        let zero = head.starts_with('0') && number(value).is_some();
1633        text = match align {
1634            Some('<') => format!("{text}{}", " ".repeat(pad)),
1635            Some('^') => format!("{}{text}{}", " ".repeat(pad / 2), " ".repeat(pad - pad / 2)),
1636            _ if zero => format!("{}{text}", "0".repeat(pad)),
1637            _ if number(value).is_some() || align == Some('>') => format!("{}{text}", " ".repeat(pad)),
1638            _ => format!("{text}{}", " ".repeat(pad)),
1639        };
1640    }
1641    text
1642}
1643
1644/// Methods of numbers, text, lists, ranges and options, iterators included, eagerly.
1645fn builtin_method(runner: &Runner, name: &str, value: Value, arguments: Vec<Value>, span: Span) -> Eval {
1646    let err = |e: String| Flow::Error(LiveError::at(span, e));
1647    let arg = |i: usize| arguments.get(i).cloned().unwrap_or(Value::Unit);
1648    let closure = |i: usize| runner.closure_arg(&arg(i), span);
1649    let call = |f: &Rc<Closure>, args: Vec<Value>| f.call(args).map_err(Flow::Error);
1650    let truthy = |v: Value| v.read() == Value::Bool(true);
1651    // Shared by every kind.
1652    match name {
1653        "clone"
1654        | "to_owned"
1655        | "into"
1656        | "as_ref"
1657        | "as_str"
1658        | "borrow"
1659        | "iter"
1660        | "into_iter"
1661        | "iter_mut"
1662        | "cloned"
1663        | "copied"
1664        | "by_ref"
1665        | "as_slice"
1666        | "to_vec"
1667        | "unwrap_or_default_kind" => {
1668            return Ok(match value {
1669                Value::Range(a, b) if name != "clone" => Value::List((a..b).map(Value::Int).collect()),
1670                other => other,
1671            });
1672        }
1673        "to_string" => return Ok(Value::Str(display(&value))),
1674        _ => {}
1675    }
1676    if name == "contains"
1677        && let Value::Range(..) | Value::FloatRange(..) = value
1678    {
1679        let (low, high, closed) = match value {
1680            Value::FloatRange(a, b) => (a, b, false),
1681            Value::Range(a, b) => (a as f64, b as f64, false),
1682            _ => (0.0, 0.0, false),
1683        };
1684        let n = number(&arg(0)).ok_or(()).or_else(|()| fail(span, "`contains` takes a number here"))?;
1685        return Ok(Value::Bool(n >= low && (n < high || (closed && n <= high))));
1686    }
1687    if let Value::Result(result) = &value {
1688        let (ok, error) = match result {
1689            Ok(v) => (Some((**v).clone()), None),
1690            Err(e) => (None, Some((**e).clone())),
1691        };
1692        let wrap_ok = |v: Value| Value::Result(Ok(Box::new(v)));
1693        return match name {
1694            "is_ok" => Ok(Value::Bool(ok.is_some())),
1695            "is_err" => Ok(Value::Bool(error.is_some())),
1696            "ok" => Ok(Value::Option(ok.map(Box::new))),
1697            "err" => Ok(Value::Option(error.map(Box::new))),
1698            "unwrap" | "expect" => {
1699                ok.ok_or(()).or_else(|()| fail(span, format!("unwrap on Err({:?})", error)))
1700            }
1701            "unwrap_or" => Ok(ok.unwrap_or_else(|| arg(0))),
1702            "unwrap_or_else" => match ok {
1703                Some(v) => Ok(v),
1704                None => call(&closure(0)?, vec![error.unwrap_or(Value::Unit)]),
1705            },
1706            "map" => match ok {
1707                Some(v) => Ok(wrap_ok(call(&closure(0)?, vec![v])?)),
1708                None => Ok(value.clone()),
1709            },
1710            "map_err" => match error {
1711                Some(e) => Ok(Value::Result(Err(Box::new(call(&closure(0)?, vec![e])?)))),
1712                None => Ok(value.clone()),
1713            },
1714            "and_then" => match ok {
1715                Some(v) => call(&closure(0)?, vec![v]),
1716                None => Ok(value.clone()),
1717            },
1718            _ => fail(span, format!("a Result has no method `{name}` the playground knows")),
1719        };
1720    }
1721    match &value {
1722        Value::Int(_) | Value::Float(_) => {
1723            let n = number(&value).unwrap_or_default();
1724            let other = number(&arg(0));
1725            let float = |f: f64| Ok(Value::Float(f));
1726            let keep = |f: f64| {
1727                Ok(if matches!(value, Value::Int(_)) && f.fract() == 0.0 {
1728                    Value::Int(f as i64)
1729                } else {
1730                    Value::Float(f)
1731                })
1732            };
1733            return match name {
1734                "abs" => keep(n.abs()),
1735                "min" => keep(n.min(other.unwrap_or(n))),
1736                "max" => keep(n.max(other.unwrap_or(n))),
1737                "clamp" => keep(n.clamp(other.unwrap_or(n), number(&arg(1)).unwrap_or(n))),
1738                "pow" | "powi" => keep(n.powi(other.unwrap_or(1.0) as i32)),
1739                "powf" => float(n.powf(other.unwrap_or(1.0))),
1740                "sqrt" => float(n.sqrt()),
1741                "sin" => float(n.sin()),
1742                "cos" => float(n.cos()),
1743                "tan" => float(n.tan()),
1744                "atan2" => float(n.atan2(other.unwrap_or(1.0))),
1745                "exp" => float(n.exp()),
1746                "ln" => float(n.ln()),
1747                "floor" => float(n.floor()),
1748                "ceil" => float(n.ceil()),
1749                "round" => float(n.round()),
1750                "trunc" => float(n.trunc()),
1751                "fract" => float(n.fract()),
1752                "signum" => keep(n.signum()),
1753                "to_radians" => float(n.to_radians()),
1754                "to_degrees" => float(n.to_degrees()),
1755                "rem_euclid" => keep(n.rem_euclid(other.unwrap_or(1.0))),
1756                "is_finite" => Ok(Value::Bool(n.is_finite())),
1757                "saturating_sub" => keep((n - other.unwrap_or(0.0)).max(0.0)),
1758                "saturating_add" | "wrapping_add" => keep(n + other.unwrap_or(0.0)),
1759                "is_even" => Ok(Value::Bool(n as i64 % 2 == 0)),
1760                _ => fail(span, format!("a number has no method `{name}` the playground knows")),
1761            };
1762        }
1763        Value::Str(text) => {
1764            let pattern = match arg(0).read() {
1765                Value::Str(s) => s,
1766                Value::Char(c) => c.to_string(),
1767                _ => String::new(),
1768            };
1769            return match name {
1770                "len" => Ok(Value::Int(text.len() as i64)),
1771                "is_empty" => Ok(Value::Bool(text.is_empty())),
1772                "to_uppercase" => Ok(Value::Str(text.to_uppercase())),
1773                "to_lowercase" => Ok(Value::Str(text.to_lowercase())),
1774                "trim" => Ok(Value::Str(text.trim().to_owned())),
1775                "as_bytes" | "bytes" => {
1776                    Ok(Value::List(text.bytes().map(|b| Value::Int(i64::from(b))).collect()))
1777                }
1778                "strip_prefix" => {
1779                    Ok(Value::Option(text.strip_prefix(&pattern).map(|t| Box::new(Value::Str(t.to_owned())))))
1780                }
1781                "strip_suffix" => {
1782                    Ok(Value::Option(text.strip_suffix(&pattern).map(|t| Box::new(Value::Str(t.to_owned())))))
1783                }
1784                "split_once" => Ok(Value::Option(text.split_once(&pattern).map(|(a, b)| {
1785                    Box::new(Value::Tuple(vec![Value::Str(a.to_owned()), Value::Str(b.to_owned())]))
1786                }))),
1787                "trim_start" => Ok(Value::Str(text.trim_start().to_owned())),
1788                "trim_end" => Ok(Value::Str(text.trim_end().to_owned())),
1789                "chars" => Ok(Value::List(text.chars().map(Value::Char).collect())),
1790                "contains" => Ok(Value::Bool(text.contains(&pattern))),
1791                "starts_with" => Ok(Value::Bool(text.starts_with(&pattern))),
1792                "ends_with" => Ok(Value::Bool(text.ends_with(&pattern))),
1793                "repeat" => Ok(Value::Str(
1794                    text.repeat(usize::try_from(number(&arg(0)).unwrap_or(0.0) as i64).unwrap_or(0)),
1795                )),
1796                "split" => Ok(Value::List(text.split(&pattern).map(|s| Value::Str(s.to_owned())).collect())),
1797                "lines" => Ok(Value::List(text.lines().map(|s| Value::Str(s.to_owned())).collect())),
1798                "replace" => Ok(Value::Str(text.replace(&pattern, &display(&arg(1))))),
1799                "parse" => Ok(match text.trim().parse::<i64>() {
1800                    Ok(n) => Value::Int(n),
1801                    Err(_) => text.trim().parse::<f64>().map(Value::Float).map_err(|e| err(e.to_string()))?,
1802                }),
1803                _ => fail(span, format!("text has no method `{name}` the playground knows")),
1804            };
1805        }
1806        Value::Char(c) => {
1807            return match name {
1808                "to_ascii_uppercase" => Ok(Value::Char(c.to_ascii_uppercase())),
1809                "to_ascii_lowercase" => Ok(Value::Char(c.to_ascii_lowercase())),
1810                "is_alphabetic" => Ok(Value::Bool(c.is_alphabetic())),
1811                "is_numeric" => Ok(Value::Bool(c.is_numeric())),
1812                _ => fail(span, format!("a char has no method `{name}` the playground knows")),
1813            };
1814        }
1815        Value::Option(option) => {
1816            let inner = option.as_deref().cloned();
1817            return match name {
1818                "is_some" => Ok(Value::Bool(inner.is_some())),
1819                "is_none" => Ok(Value::Bool(inner.is_none())),
1820                "unwrap" | "expect" => inner.ok_or(()).or_else(|()| fail(span, "unwrap on None")),
1821                "unwrap_or" => Ok(inner.unwrap_or_else(|| arg(0))),
1822                "unwrap_or_else" => match inner {
1823                    Some(v) => Ok(v),
1824                    None => call(&closure(0)?, Vec::new()),
1825                },
1826                "map" => match inner {
1827                    Some(v) => Ok(Value::Option(Some(Box::new(call(&closure(0)?, vec![v])?)))),
1828                    None => Ok(Value::Option(None)),
1829                },
1830                "and_then" => match inner {
1831                    Some(v) => call(&closure(0)?, vec![v]),
1832                    None => Ok(Value::Option(None)),
1833                },
1834                "map_or" => match inner {
1835                    Some(v) => call(&closure(1)?, vec![v]),
1836                    None => Ok(arg(0)),
1837                },
1838                "filter" => match inner {
1839                    Some(v) if truthy(call(&closure(0)?, vec![v.clone()])?) => {
1840                        Ok(Value::Option(Some(Box::new(v))))
1841                    }
1842                    _ => Ok(Value::Option(None)),
1843                },
1844                "or" => Ok(if inner.is_some() { value.clone() } else { arg(0) }),
1845                "ok_or" => Ok(Value::Result(match inner {
1846                    Some(v) => Ok(Box::new(v)),
1847                    None => Err(Box::new(arg(0))),
1848                })),
1849                "unwrap_or_default" => Ok(inner.unwrap_or(Value::Unit)),
1850                _ => list_method(runner, name, value.items().map_err(err)?, &arguments, span),
1851            };
1852        }
1853        _ => {}
1854    }
1855    match value.items() {
1856        Ok(items) => list_method(runner, name, items, &arguments, span),
1857        Err(_) => fail(span, format!("a {} has no method `{name}` the playground knows", value.kind())),
1858    }
1859}
1860
1861fn list_method(runner: &Runner, name: &str, items: Vec<Value>, arguments: &[Value], span: Span) -> Eval {
1862    let arg = |i: usize| arguments.get(i).cloned().unwrap_or(Value::Unit);
1863    let closure = |i: usize| runner.closure_arg(&arg(i), span);
1864    let call = |f: &Rc<Closure>, args: Vec<Value>| f.call(args).map_err(Flow::Error);
1865    let truthy = |v: Value| v.read() == Value::Bool(true);
1866    let count = |i: usize| usize::try_from(number(&arg(i)).unwrap_or(0.0) as i64).unwrap_or(0);
1867    let some = |v: Option<Value>| Value::Option(v.map(Box::new));
1868    Ok(match name {
1869        "map" => {
1870            let f = closure(0)?;
1871            Value::List(items.into_iter().map(|v| call(&f, vec![v])).collect::<Eval<Vec<_>>>()?)
1872        }
1873        "for_each" => {
1874            let f = closure(0)?;
1875            for item in items {
1876                call(&f, vec![item])?;
1877            }
1878            Value::Unit
1879        }
1880        "filter" => {
1881            let f = closure(0)?;
1882            let mut kept = Vec::new();
1883            for item in items {
1884                if truthy(call(&f, vec![item.clone()])?) {
1885                    kept.push(item);
1886                }
1887            }
1888            Value::List(kept)
1889        }
1890        "filter_map" | "flat_map" | "flatten" => {
1891            let f = if name == "flatten" { None } else { Some(closure(0)?) };
1892            let mut kept = Vec::new();
1893            for item in items {
1894                let out = match &f {
1895                    Some(f) => call(f, vec![item])?,
1896                    None => item,
1897                };
1898                kept.extend(out.items().map_err(|e| Flow::Error(LiveError::at(span, e)))?);
1899            }
1900            Value::List(kept)
1901        }
1902        "enumerate" => Value::List(
1903            items.into_iter().enumerate().map(|(i, v)| Value::Tuple(vec![Value::Int(i as i64), v])).collect(),
1904        ),
1905        "rev" => Value::List(items.into_iter().rev().collect()),
1906        "take" => Value::List(items.into_iter().take(count(0)).collect()),
1907        "skip" => Value::List(items.into_iter().skip(count(0)).collect()),
1908        "step_by" => Value::List(items.into_iter().step_by(count(0).max(1)).collect()),
1909        "chain" => {
1910            let mut all = items;
1911            all.extend(arg(0).items().map_err(|e| Flow::Error(LiveError::at(span, e)))?);
1912            Value::List(all)
1913        }
1914        "zip" => {
1915            let other = arg(0).items().map_err(|e| Flow::Error(LiveError::at(span, e)))?;
1916            Value::List(items.into_iter().zip(other).map(|(a, b)| Value::Tuple(vec![a, b])).collect())
1917        }
1918        "collect" | "to_vec" => Value::List(items),
1919        "len" | "count" => Value::Int(items.len() as i64),
1920        "is_empty" => Value::Bool(items.is_empty()),
1921        "first" | "next" => some(items.into_iter().next()),
1922        "last" => some(items.into_iter().last()),
1923        "get" | "nth" => some(items.into_iter().nth(count(0))),
1924        "contains" => Value::Bool(items.contains(&arg(0))),
1925        "sum" | "product" => {
1926            let product = name == "product";
1927            let mut total = if product { Value::Int(1) } else { Value::Int(0) };
1928            for item in items {
1929                total = arithmetic(if product { '*' } else { '+' }, &total, &item.read())
1930                    .map_err(|e| Flow::Error(LiveError::at(span, e)))?;
1931            }
1932            total
1933        }
1934        "min" | "max" => {
1935            let mut best: Option<Value> = None;
1936            for item in items {
1937                let better = match &best {
1938                    None => true,
1939                    Some(current) => compare(&item, current)
1940                        .is_some_and(|o| if name == "min" { o.is_lt() } else { o.is_gt() }),
1941                };
1942                if better {
1943                    best = Some(item);
1944                }
1945            }
1946            some(best)
1947        }
1948        "any" | "all" => {
1949            let f = closure(0)?;
1950            let any = name == "any";
1951            let mut answer = !any;
1952            for item in items {
1953                if truthy(call(&f, vec![item])?) == any {
1954                    answer = any;
1955                    break;
1956                }
1957            }
1958            Value::Bool(answer)
1959        }
1960        "find" | "position" => {
1961            let f = closure(0)?;
1962            let mut found = None;
1963            for (i, item) in items.into_iter().enumerate() {
1964                if truthy(call(&f, vec![item.clone()])?) {
1965                    found = Some(if name == "find" { item } else { Value::Int(i as i64) });
1966                    break;
1967                }
1968            }
1969            some(found)
1970        }
1971        "fold" => {
1972            let f = closure(1)?;
1973            let mut acc = arg(0);
1974            for item in items {
1975                acc = call(&f, vec![acc, item])?;
1976            }
1977            acc
1978        }
1979        "join" | "concat" => {
1980            let separator = if name == "join" { display(&arg(0)) } else { String::new() };
1981            Value::Str(items.iter().map(display).collect::<Vec<_>>().join(&separator))
1982        }
1983        "unwrap_or_default" => some(items.into_iter().next()),
1984        _ => return fail(span, format!("a list has no method `{name}` the playground knows")),
1985    })
1986}