diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-01-29 21:36:25 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-01-29 21:36:25 +0100 |
| commit | 24d513d8917de0a8c23916837e5ea7fbb550db8b (patch) | |
| tree | a19a64099a96bab44a7a12f58b1515326925a695 /src | |
| parent | 3cad6bf60785d899ecb78b557bf7ba3cd8903e56 (diff) | |
Enable for loop over captured args
Diffstat (limited to 'src')
| -rw-r--r-- | src/eval/mod.rs | 25 | ||||
| -rw-r--r-- | src/eval/value.rs | 11 |
2 files changed, 19 insertions, 17 deletions
diff --git a/src/eval/mod.rs b/src/eval/mod.rs index d459ba6e..05fa7eba 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -642,16 +642,8 @@ impl Eval for CallArgs { value: Spanned::new(value, span), })); } - v => { - if let Value::Dyn(dynamic) = &v { - if let Some(args) = dynamic.downcast::<Args>() { - items.extend(args.items.iter().cloned()); - continue; - } - } - - bail!(expr.span(), "cannot spread {}", v.type_name()) - } + Value::Args(args) => items.extend(args.items), + v => bail!(expr.span(), "cannot spread {}", v.type_name()), }, } } @@ -716,10 +708,6 @@ impl Eval for ClosureExpr { // Put the remaining arguments into the sink. if let Some(sink) = &sink { - dynamic! { - Args: "arguments", - } - ctx.scopes.def_mut(sink, args.take()); } @@ -868,6 +856,15 @@ impl Eval for ForExpr { (Some(k), v, Value::Dict(dict)) => { iter!(for (k => key, v => value) in dict.into_iter()); } + (None, v, Value::Args(args)) => { + iter!(for (v => value) in args.items.into_iter() + .filter(|arg| arg.name.is_none()) + .map(|arg| arg.value.v)); + } + (Some(k), v, Value::Args(args)) => { + iter!(for (k => key, v => value) in args.items.into_iter() + .map(|arg| (arg.name.map_or(Value::None, Value::Str), arg.value.v))); + } (_, _, Value::Str(_)) => { bail!(pattern.span(), "mismatched pattern"); } diff --git a/src/eval/value.rs b/src/eval/value.rs index 3b1ef3f7..e64f6cc6 100644 --- a/src/eval/value.rs +++ b/src/eval/value.rs @@ -4,7 +4,7 @@ use std::fmt::{self, Debug, Formatter}; use std::hash::Hash; use std::rc::Rc; -use super::{ops, Array, Class, Dict, Function, Node}; +use super::{ops, Args, Array, Class, Dict, Function, Node}; use crate::diag::StrResult; use crate::geom::{Angle, Color, Fractional, Length, Linear, Relative, RgbaColor}; use crate::layout::Layout; @@ -46,6 +46,8 @@ pub enum Value { Node(Node), /// An executable function. Func(Function), + /// Captured arguments to a function. + Args(Args), /// A class of nodes. Class(Class), /// A dynamic value. @@ -88,6 +90,7 @@ impl Value { Self::Dict(_) => Dict::TYPE_NAME, Self::Node(_) => Node::TYPE_NAME, Self::Func(_) => Function::TYPE_NAME, + Self::Args(_) => Args::TYPE_NAME, Self::Class(_) => Class::TYPE_NAME, Self::Dyn(v) => v.type_name(), } @@ -151,6 +154,7 @@ impl Debug for Value { Self::Dict(v) => Debug::fmt(v, f), Self::Node(_) => f.pad("<template>"), Self::Func(v) => Debug::fmt(v, f), + Self::Args(v) => Debug::fmt(v, f), Self::Class(v) => Debug::fmt(v, f), Self::Dyn(v) => Debug::fmt(v, f), } @@ -219,12 +223,12 @@ impl Dynamic { } /// Whether the wrapped type is `T`. - pub fn is<T: 'static>(&self) -> bool { + pub fn is<T: Type + 'static>(&self) -> bool { self.0.as_any().is::<T>() } /// Try to downcast to a reference to a specific type. - pub fn downcast<T: 'static>(&self) -> Option<&T> { + pub fn downcast<T: Type + 'static>(&self) -> Option<&T> { self.0.as_any().downcast_ref() } @@ -404,6 +408,7 @@ primitive! { Function: "function", move |ctx, args| v.construct(ctx, args).map(Value::Node) ) } +primitive! { Args: "arguments", Args } primitive! { Class: "class", Class } impl Cast<Value> for Value { |
