summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-02-02 16:32:30 +0100
committerLaurenz <laurmaedje@gmail.com>2022-02-02 16:32:30 +0100
commit88e50a55afff7b809d4b9d6cfaf93275bfe06f56 (patch)
treefc4792e851316f97a8c9acdc7f332d9edc62e4f9 /src
parentd3ccd55d4bdb85343ae80574b6833fac2cf22181 (diff)
Pass arguments to call and construct directly by value
Diffstat (limited to 'src')
-rw-r--r--src/eval/class.rs45
-rw-r--r--src/eval/func.rs14
-rw-r--r--src/eval/mod.rs16
3 files changed, 38 insertions, 37 deletions
diff --git a/src/eval/class.rs b/src/eval/class.rs
index 4307eecb..acdf38e6 100644
--- a/src/eval/class.rs
+++ b/src/eval/class.rs
@@ -6,15 +6,15 @@ use crate::diag::TypResult;
/// A class of nodes.
///
/// You can [construct] an instance of a class in Typst code by invoking the
-/// class as a callable. This always produces a template, but not necessarily a
-/// simple inline or block node. For example, the `text` constructor does not
-/// actually create a [`TextNode`]. Instead it applies styling to whatever node
-/// you pass in and returns it structurally unchanged.
+/// class as a callable. This always produces a template value, but not
+/// necessarily a simple inline or block node. For example, the `text`
+/// constructor does not actually create a [`TextNode`]. Instead it applies
+/// styling to whatever node you pass in and returns it structurally unchanged.
///
/// The arguments you can pass to a class constructor fall into two categories:
-/// Data that is inherent to the instance (e.g. the text of a heading) and style
-/// properties (e.g. the fill color of a heading). As the latter are often
-/// shared by many instances throughout a document, they can also be
+/// Data that is inherent to the instance (e.g. the text/content of a heading)
+/// and style properties (e.g. the fill color of a heading). As the latter are
+/// often shared by many instances throughout a document, they can also be
/// conveniently configured through class's [`set`] rule. Then, they apply to
/// all nodes that are instantiated into the template where the `set` was
/// executed.
@@ -62,25 +62,30 @@ impl Class {
self.name
}
+ /// Return the class constructor as a function.
+ pub fn constructor(&self) -> Func {
+ Func::native(self.name, self.construct)
+ }
+
/// Construct an instance of the class.
///
- /// This parses both property and data arguments (in this order) and styles
- /// the template constructed from the data with the style properties.
- pub fn construct(&self, ctx: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
- (self.construct)(ctx, args)
+ /// This parses both property and data arguments (in this order), styles the
+ /// template constructed from the data with the style properties and wraps
+ /// it in a value.
+ pub fn construct(&self, ctx: &mut EvalContext, mut args: Args) -> TypResult<Value> {
+ let value = (self.construct)(ctx, &mut args)?;
+ args.finish()?;
+ Ok(value)
}
/// Execute the class's set rule.
///
- /// This parses property arguments and writes the resulting styles into the
- /// given style map. There are no further side effects.
- pub fn set(&self, args: &mut Args, styles: &mut StyleMap) -> TypResult<()> {
- (self.set)(args, styles)
- }
-
- /// Return the class constructor as a function.
- pub fn constructor(&self) -> Func {
- Func::native(self.name, self.construct)
+ /// This parses property arguments and return the resulting styles.
+ pub fn set(&self, mut args: Args) -> TypResult<StyleMap> {
+ let mut styles = StyleMap::new();
+ (self.set)(&mut args, &mut styles)?;
+ args.finish()?;
+ Ok(styles)
}
}
diff --git a/src/eval/func.rs b/src/eval/func.rs
index ccd0932f..6d405ca4 100644
--- a/src/eval/func.rs
+++ b/src/eval/func.rs
@@ -45,15 +45,17 @@ impl Func {
}
/// Call the function in the context with the arguments.
- pub fn call(&self, ctx: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
- match self.0.as_ref() {
- Repr::Native(native) => (native.func)(ctx, args),
- Repr::Closure(closure) => closure.call(ctx, args),
+ pub fn call(&self, ctx: &mut EvalContext, mut args: Args) -> TypResult<Value> {
+ let value = match self.0.as_ref() {
+ Repr::Native(native) => (native.func)(ctx, &mut args)?,
+ Repr::Closure(closure) => closure.call(ctx, &mut args)?,
Repr::With(wrapped, applied) => {
args.items.splice(.. 0, applied.items.iter().cloned());
- wrapped.call(ctx, args)
+ return wrapped.call(ctx, args);
}
- }
+ };
+ args.finish()?;
+ Ok(value)
}
/// Apply the given arguments to the function.
diff --git a/src/eval/mod.rs b/src/eval/mod.rs
index 33ee23ca..7c038c2a 100644
--- a/src/eval/mod.rs
+++ b/src/eval/mod.rs
@@ -189,10 +189,8 @@ fn eval_markup(
MarkupNode::Expr(Expr::Set(set)) => {
let class = set.class();
let class = class.eval(ctx)?.cast::<Class>().at(class.span())?;
- let mut args = set.args().eval(ctx)?;
- let mut styles = StyleMap::new();
- class.set(&mut args, &mut styles)?;
- args.finish()?;
+ let args = set.args().eval(ctx)?;
+ let styles = class.set(args)?;
let tail = eval_markup(ctx, nodes)?;
tail.styled_with_map(styles)
}
@@ -590,7 +588,7 @@ impl Eval for CallExpr {
fn eval(&self, ctx: &mut EvalContext) -> TypResult<Self::Output> {
let span = self.callee().span();
let callee = self.callee().eval(ctx)?;
- let mut args = self.args().eval(ctx)?;
+ let args = self.args().eval(ctx)?;
match callee {
Value::Array(array) => {
@@ -603,16 +601,12 @@ impl Eval for CallExpr {
Value::Func(func) => {
let point = || Tracepoint::Call(func.name().map(ToString::to_string));
- let value = func.call(ctx, &mut args).trace(point, self.span())?;
- args.finish()?;
- Ok(value)
+ func.call(ctx, args).trace(point, self.span())
}
Value::Class(class) => {
let point = || Tracepoint::Call(Some(class.name().to_string()));
- let value = class.construct(ctx, &mut args).trace(point, self.span())?;
- args.finish()?;
- Ok(value)
+ class.construct(ctx, args).trace(point, self.span())
}
v => bail!(