summaryrefslogtreecommitdiff
path: root/src/eval/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval/mod.rs')
-rw-r--r--src/eval/mod.rs41
1 files changed, 28 insertions, 13 deletions
diff --git a/src/eval/mod.rs b/src/eval/mod.rs
index 5542de89..e9d62a69 100644
--- a/src/eval/mod.rs
+++ b/src/eval/mod.rs
@@ -38,7 +38,7 @@ use unicode_segmentation::UnicodeSegmentation;
use crate::diag::{At, StrResult, Trace, Tracepoint, TypResult};
use crate::geom::{Angle, Em, Fraction, Length, Ratio};
use crate::library;
-use crate::model::{Content, StyleMap};
+use crate::model::{Content, Pattern, Recipe, StyleEntry, StyleMap};
use crate::syntax::ast::*;
use crate::syntax::{Span, Spanned};
use crate::util::EcoString;
@@ -79,8 +79,9 @@ fn eval_markup(
eval_markup(ctx, scp, nodes)?.styled_with_map(styles)
}
MarkupNode::Expr(Expr::Show(show)) => {
- let styles = show.eval(ctx, scp)?;
- eval_markup(ctx, scp, nodes)?.styled_with_map(styles)
+ let recipe = show.eval(ctx, scp)?;
+ eval_markup(ctx, scp, nodes)?
+ .styled_with_entry(StyleEntry::Recipe(recipe).into())
}
MarkupNode::Expr(Expr::Wrap(wrap)) => {
let tail = eval_markup(ctx, scp, nodes)?;
@@ -434,8 +435,17 @@ impl Eval for FieldAccess {
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
let object = self.object().eval(ctx, scp)?;
+ let span = self.field().span();
+ let field = self.field().take();
+
Ok(match object {
- Value::Dict(dict) => dict.get(self.field().take()).at(self.span())?.clone(),
+ Value::Dict(dict) => dict.get(&field).at(span)?.clone(),
+
+ Value::Content(Content::Show(_, Some(dict))) => dict
+ .get(&field)
+ .map_err(|_| format!("unknown field {field:?}"))
+ .at(span)?
+ .clone(),
v => bail!(
self.object().span(),
@@ -455,7 +465,7 @@ impl Eval for FuncCall {
Ok(match callee {
Value::Array(array) => array.get(args.into_index()?).at(self.span())?.clone(),
- Value::Dict(dict) => dict.get(args.into_key()?).at(self.span())?.clone(),
+ Value::Dict(dict) => dict.get(&args.into_key()?).at(self.span())?.clone(),
Value::Func(func) => {
let point = || Tracepoint::Call(func.name().map(ToString::to_string));
func.call(ctx, args).trace(point, self.span())?
@@ -615,13 +625,12 @@ impl Eval for SetExpr {
}
impl Eval for ShowExpr {
- type Output = StyleMap;
+ type Output = Recipe;
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
// Evaluate the target function.
- let target = self.target();
- let target_span = target.span();
- let target = target.eval(ctx, scp)?.cast::<Func>().at(target_span)?;
+ let pattern = self.pattern();
+ let pattern = pattern.eval(ctx, scp)?.cast::<Pattern>().at(pattern.span())?;
// Collect captured variables.
let captured = {
@@ -630,18 +639,24 @@ impl Eval for ShowExpr {
visitor.finish()
};
+ // Define parameters.
+ let mut params = vec![];
+ if let Some(binding) = self.binding() {
+ params.push((binding.take(), None));
+ }
+
// Define the recipe function.
let body = self.body();
- let body_span = body.span();
- let recipe = Func::from_closure(Closure {
+ let span = body.span();
+ let func = Func::from_closure(Closure {
name: None,
captured,
- params: vec![(self.binding().take(), None)],
+ params,
sink: None,
body,
});
- Ok(target.show(recipe, body_span).at(target_span)?)
+ Ok(Recipe { pattern, func, span })
}
}