1use 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#[derive(Clone, Debug, PartialEq, Eq)]
21pub struct LiveError {
22 pub line: usize,
24 pub column: usize,
26 pub length: usize,
28 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 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
55enum 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
71struct 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
106pub(crate) struct Function {
108 sig: syn::Signature,
109 block: syn::Block,
110}
111
112#[derive(Clone)]
114enum Shape {
115 Unit,
116 Tuple(usize),
117 Named(Vec<String>),
118}
119
120pub(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 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
206pub(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
217enum Body {
220 Code(Box<Code>),
221 Path(Vec<String>),
222 Host(HostFn),
223}
224
225struct Code {
227 params: Vec<Pat>,
228 body: Expr,
229 scope: Rc<Scope>,
230}
231
232pub 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 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 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
290pub 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
354fn 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 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 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 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 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 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 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 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 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("e_path(&literal.path))
752 ),
753 ),
754 }
755 }
756
757 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 _ 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 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 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 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 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 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
1444fn 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 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
1562fn 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
1574fn 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
1644fn 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 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}