Pass arguments to call and construct directly by value
This commit is contained in:
parent
d3ccd55d4b
commit
88e50a55af
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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!(
|
||||
|
Loading…
x
Reference in New Issue
Block a user