summaryrefslogtreecommitdiff
path: root/src/eval
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-04-11 15:52:57 +0200
committerLaurenz <laurmaedje@gmail.com>2022-04-11 15:52:57 +0200
commit938b0af889b8fbe6265695b1b8e54aee338ba87f (patch)
tree0121d733a556576d147742d460fe4df0d3c8cb1d /src/eval
parent790bd536eba76a2a48d61ea6b1bde78cde3d31f3 (diff)
Spreading into arrays and dictionaries
Diffstat (limited to 'src/eval')
-rw-r--r--src/eval/mod.rs41
1 files changed, 37 insertions, 4 deletions
diff --git a/src/eval/mod.rs b/src/eval/mod.rs
index 3f580178..9e5a8555 100644
--- a/src/eval/mod.rs
+++ b/src/eval/mod.rs
@@ -39,6 +39,8 @@ pub use show::*;
pub use styles::*;
pub use value::*;
+use std::collections::BTreeMap;
+
use parking_lot::{MappedRwLockWriteGuard, RwLockWriteGuard};
use unicode_segmentation::UnicodeSegmentation;
@@ -307,7 +309,21 @@ impl Eval for ArrayExpr {
type Output = Array;
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
- self.items().map(|expr| expr.eval(ctx, scp)).collect()
+ let items = self.items();
+
+ let mut vec = Vec::with_capacity(items.size_hint().0);
+ for item in items {
+ match item {
+ ArrayItem::Pos(expr) => vec.push(expr.eval(ctx, scp)?),
+ ArrayItem::Spread(expr) => match expr.eval(ctx, scp)? {
+ Value::None => {}
+ Value::Array(array) => vec.extend(array.into_iter()),
+ v => bail!(expr.span(), "cannot spread {} into array", v.type_name()),
+ },
+ }
+ }
+
+ Ok(Array::from_vec(vec))
}
}
@@ -315,9 +331,26 @@ impl Eval for DictExpr {
type Output = Dict;
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
- self.items()
- .map(|x| Ok((x.name().take(), x.expr().eval(ctx, scp)?)))
- .collect()
+ let mut map = BTreeMap::new();
+
+ for item in self.items() {
+ match item {
+ DictItem::Named(named) => {
+ map.insert(named.name().take(), named.expr().eval(ctx, scp)?);
+ }
+ DictItem::Spread(expr) => match expr.eval(ctx, scp)? {
+ Value::None => {}
+ Value::Dict(dict) => map.extend(dict.into_iter()),
+ v => bail!(
+ expr.span(),
+ "cannot spread {} into dictionary",
+ v.type_name()
+ ),
+ },
+ }
+ }
+
+ Ok(Dict::from_map(map))
}
}