summaryrefslogtreecommitdiff
path: root/src/eval
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval')
-rw-r--r--src/eval/mod.rs25
-rw-r--r--src/eval/value.rs11
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 {