diff options
Diffstat (limited to 'src/eval')
| -rw-r--r-- | src/eval/class.rs | 11 | ||||
| -rw-r--r-- | src/eval/func.rs | 32 | ||||
| -rw-r--r-- | src/eval/layout.rs | 46 | ||||
| -rw-r--r-- | src/eval/mod.rs | 360 | ||||
| -rw-r--r-- | src/eval/module.rs | 20 | ||||
| -rw-r--r-- | src/eval/scope.rs | 5 | ||||
| -rw-r--r-- | src/eval/show.rs | 8 | ||||
| -rw-r--r-- | src/eval/styles.rs | 12 | ||||
| -rw-r--r-- | src/eval/template.rs | 67 |
9 files changed, 286 insertions, 275 deletions
diff --git a/src/eval/class.rs b/src/eval/class.rs index 5601fb0b..5e1857d7 100644 --- a/src/eval/class.rs +++ b/src/eval/class.rs @@ -2,8 +2,9 @@ use std::any::TypeId; use std::fmt::{self, Debug, Formatter, Write}; use std::hash::{Hash, Hasher}; -use super::{Args, Func, StyleMap, Template, Value, Vm}; +use super::{Args, Func, StyleMap, Template, Value}; use crate::diag::TypResult; +use crate::Context; /// A class of nodes. /// @@ -38,7 +39,7 @@ use crate::diag::TypResult; pub struct Class { name: &'static str, id: TypeId, - construct: fn(&mut Vm, &mut Args) -> TypResult<Value>, + construct: fn(&mut Context, &mut Args) -> TypResult<Value>, set: fn(&mut Args, &mut StyleMap) -> TypResult<()>, } @@ -81,8 +82,8 @@ impl Class { /// 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, vm: &mut Vm, mut args: Args) -> TypResult<Value> { - let value = (self.construct)(vm, &mut args)?; + pub fn construct(&self, ctx: &mut Context, mut args: Args) -> TypResult<Value> { + let value = (self.construct)(ctx, &mut args)?; args.finish()?; Ok(value) } @@ -125,7 +126,7 @@ pub trait Construct { /// /// This is passed only the arguments that remain after execution of the /// class's set rule. - fn construct(vm: &mut Vm, args: &mut Args) -> TypResult<Template>; + fn construct(ctx: &mut Context, args: &mut Args) -> TypResult<Template>; } /// Set style properties of a class. diff --git a/src/eval/func.rs b/src/eval/func.rs index 128509f8..cd54a140 100644 --- a/src/eval/func.rs +++ b/src/eval/func.rs @@ -2,11 +2,12 @@ use std::fmt::{self, Debug, Formatter, Write}; use std::hash::{Hash, Hasher}; use std::sync::Arc; -use super::{Cast, Eval, Scope, Value, Vm}; +use super::{Cast, Eval, Scope, Scopes, Value}; use crate::diag::{At, TypResult}; use crate::syntax::ast::Expr; use crate::syntax::{Span, Spanned}; use crate::util::EcoString; +use crate::Context; /// An evaluatable function. #[derive(Clone, Hash)] @@ -27,7 +28,7 @@ impl Func { /// Create a new function from a native rust function. pub fn native( name: &'static str, - func: fn(&mut Vm, &mut Args) -> TypResult<Value>, + func: fn(&mut Context, &mut Args) -> TypResult<Value>, ) -> Self { Self(Arc::new(Repr::Native(Native { name, func }))) } @@ -46,14 +47,14 @@ impl Func { } } - /// Call the function in the context with the arguments. - pub fn call(&self, vm: &mut Vm, mut args: Args) -> TypResult<Value> { + /// Call the function with a virtual machine and arguments. + pub fn call(&self, ctx: &mut Context, mut args: Args) -> TypResult<Value> { let value = match self.0.as_ref() { - Repr::Native(native) => (native.func)(vm, &mut args)?, - Repr::Closure(closure) => closure.call(vm, &mut args)?, + 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()); - return wrapped.call(vm, args); + return wrapped.call(ctx, args); } }; args.finish()?; @@ -88,7 +89,7 @@ struct Native { /// The name of the function. pub name: &'static str, /// The function pointer. - pub func: fn(&mut Vm, &mut Args) -> TypResult<Value>, + pub func: fn(&mut Context, &mut Args) -> TypResult<Value>, } impl Hash for Native { @@ -115,15 +116,15 @@ pub struct Closure { impl Closure { /// Call the function in the context with the arguments. - pub fn call(&self, vm: &mut Vm, args: &mut Args) -> TypResult<Value> { + pub fn call(&self, ctx: &mut Context, args: &mut Args) -> TypResult<Value> { // Don't leak the scopes from the call site. Instead, we use the // scope of captured variables we collected earlier. - let prev_scopes = std::mem::take(&mut vm.scopes); - vm.scopes.top = self.captured.clone(); + let mut scp = Scopes::new(None); + scp.top = self.captured.clone(); // Parse the arguments according to the parameter list. for (param, default) in &self.params { - vm.scopes.top.def_mut(param, match default { + scp.top.def_mut(param, match default { None => args.expect::<Value>(param)?, Some(default) => { args.named::<Value>(param)?.unwrap_or_else(|| default.clone()) @@ -133,14 +134,11 @@ impl Closure { // Put the remaining arguments into the sink. if let Some(sink) = &self.sink { - vm.scopes.top.def_mut(sink, args.take()); + scp.top.def_mut(sink, args.take()); } // Evaluate the body. - let value = self.body.eval(vm)?; - - // Restore the call site scopes. - vm.scopes = prev_scopes; + let value = self.body.eval(ctx, &mut scp)?; Ok(value) } diff --git a/src/eval/layout.rs b/src/eval/layout.rs index 7608023a..1090aafc 100644 --- a/src/eval/layout.rs +++ b/src/eval/layout.rs @@ -11,7 +11,7 @@ use crate::frame::{Element, Frame, Geometry, Shape, Stroke}; use crate::geom::{Align, Length, Linear, Paint, Point, Sides, Size, Spec, Transform}; use crate::library::{AlignNode, PadNode, TransformNode, MOVE}; use crate::util::Prehashed; -use crate::Vm; +use crate::Context; /// A node that can be layouted into a sequence of regions. /// @@ -21,7 +21,7 @@ pub trait Layout { /// Layout the node into the given regions, producing constrained frames. fn layout( &self, - vm: &mut Vm, + ctx: &mut Context, regions: &Regions, styles: StyleChain, ) -> TypResult<Vec<Arc<Frame>>>; @@ -36,14 +36,14 @@ pub trait Layout { } /// A sequence of regions to layout into. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub struct Regions { /// The (remaining) size of the first region. pub first: Size, /// The base size for relative sizing. pub base: Size, /// The height of followup regions. The width is the same for all regions. - pub backlog: std::vec::IntoIter<Length>, + pub backlog: Vec<Length>, /// The height of the final region that is repeated once the backlog is /// drained. The width is the same for all regions. pub last: Option<Length>, @@ -58,7 +58,7 @@ impl Regions { Self { first: size, base, - backlog: vec![].into_iter(), + backlog: vec![], last: None, expand, } @@ -69,7 +69,7 @@ impl Regions { Self { first: size, base, - backlog: vec![].into_iter(), + backlog: vec![], last: Some(size.y), expand, } @@ -87,13 +87,7 @@ impl Regions { Self { first: f(self.first), base: f(self.base), - backlog: self - .backlog - .as_slice() - .iter() - .map(|&y| f(Size::new(x, y)).y) - .collect::<Vec<_>>() - .into_iter(), + backlog: self.backlog.iter().map(|&y| f(Size::new(x, y)).y).collect(), last: self.last.map(|y| f(Size::new(x, y)).y), expand: self.expand, } @@ -113,7 +107,10 @@ impl Regions { /// Advance to the next region if there is any. pub fn next(&mut self) { - if let Some(height) = self.backlog.next().or(self.last) { + if let Some(height) = (!self.backlog.is_empty()) + .then(|| self.backlog.remove(0)) + .or(self.last) + { self.first.y = height; self.base.y = height; } @@ -125,7 +122,7 @@ impl Regions { /// This iterater may be infinite. pub fn iter(&self) -> impl Iterator<Item = Size> + '_ { let first = std::iter::once(self.first); - let backlog = self.backlog.as_slice().iter(); + let backlog = self.backlog.iter(); let last = self.last.iter().cycle(); first.chain(backlog.chain(last).map(|&h| Size::new(self.first.x, h))) } @@ -218,15 +215,14 @@ impl LayoutNode { } impl Layout for LayoutNode { - #[track_caller] fn layout( &self, - vm: &mut Vm, + ctx: &mut Context, regions: &Regions, styles: StyleChain, ) -> TypResult<Vec<Arc<Frame>>> { // TODO(query) - self.0.layout(vm, regions, styles.barred(self.id())) + self.0.layout(ctx, regions, styles.barred(self.id())) } fn pack(self) -> LayoutNode { @@ -274,7 +270,7 @@ struct EmptyNode; impl Layout for EmptyNode { fn layout( &self, - _: &mut Vm, + _: &mut Context, regions: &Regions, _: StyleChain, ) -> TypResult<Vec<Arc<Frame>>> { @@ -296,7 +292,7 @@ struct SizedNode { impl Layout for SizedNode { fn layout( &self, - vm: &mut Vm, + ctx: &mut Context, regions: &Regions, styles: StyleChain, ) -> TypResult<Vec<Arc<Frame>>> { @@ -319,7 +315,7 @@ impl Layout for SizedNode { }; // Layout the child. - let mut frames = self.child.layout(vm, &pod, styles)?; + let mut frames = self.child.layout(ctx, &pod, styles)?; // Ensure frame size matches regions size if expansion is on. let frame = &mut frames[0]; @@ -342,11 +338,11 @@ struct FillNode { impl Layout for FillNode { fn layout( &self, - vm: &mut Vm, + ctx: &mut Context, regions: &Regions, styles: StyleChain, ) -> TypResult<Vec<Arc<Frame>>> { - let mut frames = self.child.layout(vm, regions, styles)?; + let mut frames = self.child.layout(ctx, regions, styles)?; for frame in &mut frames { let shape = Shape::filled(Geometry::Rect(frame.size), self.fill); Arc::make_mut(frame).prepend(Point::zero(), Element::Shape(shape)); @@ -367,11 +363,11 @@ struct StrokeNode { impl Layout for StrokeNode { fn layout( &self, - vm: &mut Vm, + ctx: &mut Context, regions: &Regions, styles: StyleChain, ) -> TypResult<Vec<Arc<Frame>>> { - let mut frames = self.child.layout(vm, regions, styles)?; + let mut frames = self.child.layout(ctx, regions, styles)?; for frame in &mut frames { let shape = Shape::stroked(Geometry::Rect(frame.size), self.stroke); Arc::make_mut(frame).prepend(Point::zero(), Element::Shape(shape)); diff --git a/src/eval/mod.rs b/src/eval/mod.rs index a67a21d4..bc6c8fc8 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -13,6 +13,7 @@ mod class; mod collapse; mod func; mod layout; +mod module; mod ops; mod scope; mod show; @@ -25,15 +26,13 @@ pub use collapse::*; pub use dict::*; pub use func::*; pub use layout::*; +pub use module::*; pub use scope::*; pub use show::*; pub use styles::*; pub use template::*; pub use value::*; -use std::io; -use std::mem; - use unicode_segmentation::UnicodeSegmentation; use crate::diag::{At, Error, StrResult, Trace, Tracepoint, TypResult}; @@ -42,17 +41,7 @@ use crate::library; use crate::syntax::ast::*; use crate::syntax::{Span, Spanned}; use crate::util::EcoString; -use crate::Vm; - -/// An evaluated module, ready for importing or conversion to a root layout -/// tree. -#[derive(Debug, Clone)] -pub struct Module { - /// The top-level definitions that were bound in this module. - pub scope: Scope, - /// The module's layoutable contents. - pub template: Template, -} +use crate::Context; /// Evaluate an expression. pub trait Eval { @@ -60,20 +49,21 @@ pub trait Eval { type Output; /// Evaluate the expression to the output value. - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output>; + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output>; } impl Eval for Markup { type Output = Template; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { - eval_markup(vm, &mut self.nodes()) + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { + eval_markup(ctx, scp, &mut self.nodes()) } } /// Evaluate a stream of markup nodes. fn eval_markup( - vm: &mut Vm, + ctx: &mut Context, + scp: &mut Scopes, nodes: &mut impl Iterator<Item = MarkupNode>, ) -> TypResult<Template> { let mut seq = Vec::with_capacity(nodes.size_hint().1.unwrap_or_default()); @@ -81,19 +71,19 @@ fn eval_markup( while let Some(node) = nodes.next() { seq.push(match node { MarkupNode::Expr(Expr::Set(set)) => { - let styles = set.eval(vm)?; - eval_markup(vm, nodes)?.styled_with_map(styles) + let styles = set.eval(ctx, scp)?; + eval_markup(ctx, scp, nodes)?.styled_with_map(styles) } MarkupNode::Expr(Expr::Show(show)) => { - let styles = show.eval(vm)?; - eval_markup(vm, nodes)?.styled_with_map(styles) + let styles = show.eval(ctx, scp)?; + eval_markup(ctx, scp, nodes)?.styled_with_map(styles) } MarkupNode::Expr(Expr::Wrap(wrap)) => { - let tail = eval_markup(vm, nodes)?; - vm.scopes.top.def_mut(wrap.binding().take(), tail); - wrap.body().eval(vm)?.display() + let tail = eval_markup(ctx, scp, nodes)?; + scp.top.def_mut(wrap.binding().take(), tail); + wrap.body().eval(ctx, scp)?.display() } - _ => node.eval(vm)?, + _ => node.eval(ctx, scp)?, }); } @@ -103,20 +93,20 @@ fn eval_markup( impl Eval for MarkupNode { type Output = Template; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { Ok(match self { Self::Space => Template::Space, Self::Linebreak => Template::Linebreak, Self::Parbreak => Template::Parbreak, Self::Text(text) => Template::Text(text.clone()), - Self::Strong(strong) => strong.eval(vm)?, - Self::Emph(emph) => emph.eval(vm)?, - Self::Raw(raw) => raw.eval(vm)?, - Self::Math(math) => math.eval(vm)?, - Self::Heading(heading) => heading.eval(vm)?, - Self::List(list) => list.eval(vm)?, - Self::Enum(enum_) => enum_.eval(vm)?, - Self::Expr(expr) => expr.eval(vm)?.display(), + Self::Strong(strong) => strong.eval(ctx, scp)?, + Self::Emph(emph) => emph.eval(ctx, scp)?, + Self::Raw(raw) => raw.eval(ctx, scp)?, + Self::Math(math) => math.eval(ctx, scp)?, + Self::Heading(heading) => heading.eval(ctx, scp)?, + Self::List(list) => list.eval(ctx, scp)?, + Self::Enum(enum_) => enum_.eval(ctx, scp)?, + Self::Expr(expr) => expr.eval(ctx, scp)?.display(), }) } } @@ -124,23 +114,27 @@ impl Eval for MarkupNode { impl Eval for StrongNode { type Output = Template; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { - Ok(Template::show(library::StrongNode(self.body().eval(vm)?))) + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { + Ok(Template::show(library::StrongNode( + self.body().eval(ctx, scp)?, + ))) } } impl Eval for EmphNode { type Output = Template; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { - Ok(Template::show(library::EmphNode(self.body().eval(vm)?))) + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { + Ok(Template::show(library::EmphNode( + self.body().eval(ctx, scp)?, + ))) } } impl Eval for RawNode { type Output = Template; - fn eval(&self, _: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, _: &mut Context, _: &mut Scopes) -> TypResult<Self::Output> { let template = Template::show(library::RawNode { text: self.text.clone(), block: self.block, @@ -155,7 +149,7 @@ impl Eval for RawNode { impl Eval for MathNode { type Output = Template; - fn eval(&self, _: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, _: &mut Context, _: &mut Scopes) -> TypResult<Self::Output> { Ok(Template::show(library::MathNode { formula: self.formula.clone(), display: self.display, @@ -166,9 +160,9 @@ impl Eval for MathNode { impl Eval for HeadingNode { type Output = Template; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { Ok(Template::show(library::HeadingNode { - body: self.body().eval(vm)?, + body: self.body().eval(ctx, scp)?, level: self.level(), })) } @@ -177,10 +171,10 @@ impl Eval for HeadingNode { impl Eval for ListNode { type Output = Template; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { Ok(Template::List(library::ListItem { number: None, - body: Box::new(self.body().eval(vm)?), + body: Box::new(self.body().eval(ctx, scp)?), })) } } @@ -188,10 +182,10 @@ impl Eval for ListNode { impl Eval for EnumNode { type Output = Template; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { Ok(Template::Enum(library::ListItem { number: self.number(), - body: Box::new(self.body().eval(vm)?), + body: Box::new(self.body().eval(ctx, scp)?), })) } } @@ -199,33 +193,33 @@ impl Eval for EnumNode { impl Eval for Expr { type Output = Value; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { match self { - Self::Lit(v) => v.eval(vm), - Self::Ident(v) => v.eval(vm), - Self::Array(v) => v.eval(vm).map(Value::Array), - Self::Dict(v) => v.eval(vm).map(Value::Dict), - Self::Template(v) => v.eval(vm).map(Value::Template), - Self::Group(v) => v.eval(vm), - Self::Block(v) => v.eval(vm), - Self::Call(v) => v.eval(vm), - Self::Closure(v) => v.eval(vm), - Self::With(v) => v.eval(vm), - Self::Unary(v) => v.eval(vm), - Self::Binary(v) => v.eval(vm), - Self::Let(v) => v.eval(vm), + Self::Lit(v) => v.eval(ctx, scp), + Self::Ident(v) => v.eval(ctx, scp), + Self::Array(v) => v.eval(ctx, scp).map(Value::Array), + Self::Dict(v) => v.eval(ctx, scp).map(Value::Dict), + Self::Template(v) => v.eval(ctx, scp).map(Value::Template), + Self::Group(v) => v.eval(ctx, scp), + Self::Block(v) => v.eval(ctx, scp), + Self::Call(v) => v.eval(ctx, scp), + Self::Closure(v) => v.eval(ctx, scp), + Self::With(v) => v.eval(ctx, scp), + Self::Unary(v) => v.eval(ctx, scp), + Self::Binary(v) => v.eval(ctx, scp), + Self::Let(v) => v.eval(ctx, scp), Self::Set(_) | Self::Show(_) | Self::Wrap(_) => { Err("set, show and wrap are only allowed directly in markup") .at(self.span()) } - Self::If(v) => v.eval(vm), - Self::While(v) => v.eval(vm), - Self::For(v) => v.eval(vm), - Self::Import(v) => v.eval(vm), - Self::Include(v) => v.eval(vm), - Self::Break(v) => v.eval(vm), - Self::Continue(v) => v.eval(vm), - Self::Return(v) => v.eval(vm), + Self::If(v) => v.eval(ctx, scp), + Self::While(v) => v.eval(ctx, scp), + Self::For(v) => v.eval(ctx, scp), + Self::Import(v) => v.eval(ctx, scp), + Self::Include(v) => v.eval(ctx, scp).map(Value::Template), + Self::Break(v) => v.eval(ctx, scp), + Self::Continue(v) => v.eval(ctx, scp), + Self::Return(v) => v.eval(ctx, scp), } } } @@ -233,7 +227,7 @@ impl Eval for Expr { impl Eval for Lit { type Output = Value; - fn eval(&self, _: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, _: &mut Context, _: &mut Scopes) -> TypResult<Self::Output> { Ok(match self.kind() { LitKind::None => Value::None, LitKind::Auto => Value::Auto, @@ -252,8 +246,8 @@ impl Eval for Lit { impl Eval for Ident { type Output = Value; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { - match vm.scopes.get(self) { + fn eval(&self, _: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { + match scp.get(self) { Some(slot) => Ok(slot.read().unwrap().clone()), None => bail!(self.span(), "unknown variable"), } @@ -263,17 +257,17 @@ impl Eval for Ident { impl Eval for ArrayExpr { type Output = Array; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { - self.items().map(|expr| expr.eval(vm)).collect() + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { + self.items().map(|expr| expr.eval(ctx, scp)).collect() } } impl Eval for DictExpr { type Output = Dict; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { self.items() - .map(|x| Ok((x.name().take(), x.expr().eval(vm)?))) + .map(|x| Ok((x.name().take(), x.expr().eval(ctx, scp)?))) .collect() } } @@ -281,10 +275,10 @@ impl Eval for DictExpr { impl Eval for TemplateExpr { type Output = Template; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { - vm.scopes.enter(); - let template = self.body().eval(vm)?; - vm.scopes.exit(); + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { + scp.enter(); + let template = self.body().eval(ctx, scp)?; + scp.exit(); Ok(template) } } @@ -292,24 +286,24 @@ impl Eval for TemplateExpr { impl Eval for GroupExpr { type Output = Value; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { - self.expr().eval(vm) + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { + self.expr().eval(ctx, scp) } } impl Eval for BlockExpr { type Output = Value; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { - vm.scopes.enter(); + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { + scp.enter(); let mut output = Value::None; for expr in self.exprs() { - let value = expr.eval(vm)?; + let value = expr.eval(ctx, scp)?; output = ops::join(output, value).at(expr.span())?; } - vm.scopes.exit(); + scp.exit(); Ok(output) } @@ -318,8 +312,8 @@ impl Eval for BlockExpr { impl Eval for UnaryExpr { type Output = Value; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { - let value = self.expr().eval(vm)?; + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { + let value = self.expr().eval(ctx, scp)?; let result = match self.op() { UnOp::Pos => ops::pos(value), UnOp::Neg => ops::neg(value), @@ -332,25 +326,25 @@ impl Eval for UnaryExpr { impl Eval for BinaryExpr { type Output = Value; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { match self.op() { - BinOp::Add => self.apply(vm, ops::add), - BinOp::Sub => self.apply(vm, ops::sub), - BinOp::Mul => self.apply(vm, ops::mul), - BinOp::Div => self.apply(vm, ops::div), - BinOp::And => self.apply(vm, ops::and), - BinOp::Or => self.apply(vm, ops::or), - BinOp::Eq => self.apply(vm, ops::eq), - BinOp::Neq => self.apply(vm, ops::neq), - BinOp::Lt => self.apply(vm, ops::lt), - BinOp::Leq => self.apply(vm, ops::leq), - BinOp::Gt => self.apply(vm, ops::gt), - BinOp::Geq => self.apply(vm, ops::geq), - BinOp::Assign => self.assign(vm, |_, b| Ok(b)), - BinOp::AddAssign => self.assign(vm, ops::add), - BinOp::SubAssign => self.assign(vm, ops::sub), - BinOp::MulAssign => self.assign(vm, ops::mul), - BinOp::DivAssign => self.assign(vm, ops::div), + BinOp::Add => self.apply(ctx, scp, ops::add), + BinOp::Sub => self.apply(ctx, scp, ops::sub), + BinOp::Mul => self.apply(ctx, scp, ops::mul), + BinOp::Div => self.apply(ctx, scp, ops::div), + BinOp::And => self.apply(ctx, scp, ops::and), + BinOp::Or => self.apply(ctx, scp, ops::or), + BinOp::Eq => self.apply(ctx, scp, ops::eq), + BinOp::Neq => self.apply(ctx, scp, ops::neq), + BinOp::Lt => self.apply(ctx, scp, ops::lt), + BinOp::Leq => self.apply(ctx, scp, ops::leq), + BinOp::Gt => self.apply(ctx, scp, ops::gt), + BinOp::Geq => self.apply(ctx, scp, ops::geq), + BinOp::Assign => self.assign(ctx, scp, |_, b| Ok(b)), + BinOp::AddAssign => self.assign(ctx, scp, ops::add), + BinOp::SubAssign => self.assign(ctx, scp, ops::sub), + BinOp::MulAssign => self.assign(ctx, scp, ops::mul), + BinOp::DivAssign => self.assign(ctx, scp, ops::div), } } } @@ -359,10 +353,11 @@ impl BinaryExpr { /// Apply a basic binary operation. fn apply( &self, - vm: &mut Vm, + ctx: &mut Context, + scp: &mut Scopes, op: fn(Value, Value) -> StrResult<Value>, ) -> TypResult<Value> { - let lhs = self.lhs().eval(vm)?; + let lhs = self.lhs().eval(ctx, scp)?; // Short-circuit boolean operations. if (self.op() == BinOp::And && lhs == Value::Bool(false)) @@ -371,21 +366,23 @@ impl BinaryExpr { return Ok(lhs); } - let rhs = self.rhs().eval(vm)?; + let rhs = self.rhs().eval(ctx, scp)?; op(lhs, rhs).at(self.span()) } /// Apply an assignment operation. fn assign( &self, - vm: &mut Vm, + ctx: &mut Context, + scp: &mut Scopes, op: fn(Value, Value) -> StrResult<Value>, ) -> TypResult<Value> { - let rhs = self.rhs().eval(vm)?; + let rhs = self.rhs().eval(ctx, scp)?; self.lhs().access( - vm, + ctx, + scp, Box::new(|target| { - let lhs = mem::take(&mut *target); + let lhs = std::mem::take(&mut *target); *target = op(lhs, rhs).at(self.span())?; Ok(()) }), @@ -397,10 +394,10 @@ impl BinaryExpr { impl Eval for CallExpr { type Output = Value; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { let span = self.callee().span(); - let callee = self.callee().eval(vm)?; - let args = self.args().eval(vm)?; + let callee = self.callee().eval(ctx, scp)?; + let args = self.args().eval(ctx, scp)?; match callee { Value::Array(array) => { @@ -413,12 +410,12 @@ impl Eval for CallExpr { Value::Func(func) => { let point = || Tracepoint::Call(func.name().map(ToString::to_string)); - func.call(vm, args).trace(point, self.span()) + func.call(ctx, args).trace(point, self.span()) } Value::Class(class) => { let point = || Tracepoint::Call(Some(class.name().to_string())); - class.construct(vm, args).trace(point, self.span()) + class.construct(ctx, args).trace(point, self.span()) } v => bail!( @@ -433,7 +430,7 @@ impl Eval for CallExpr { impl Eval for CallArgs { type Output = Args; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { let mut items = Vec::new(); for arg in self.items() { @@ -443,17 +440,20 @@ impl Eval for CallArgs { items.push(Arg { span, name: None, - value: Spanned::new(expr.eval(vm)?, expr.span()), + value: Spanned::new(expr.eval(ctx, scp)?, expr.span()), }); } CallArg::Named(named) => { items.push(Arg { span, name: Some(named.name().take()), - value: Spanned::new(named.expr().eval(vm)?, named.expr().span()), + value: Spanned::new( + named.expr().eval(ctx, scp)?, + named.expr().span(), + ), }); } - CallArg::Spread(expr) => match expr.eval(vm)? { + CallArg::Spread(expr) => match expr.eval(ctx, scp)? { Value::None => {} Value::Array(array) => { items.extend(array.into_iter().map(|value| Arg { @@ -482,13 +482,13 @@ impl Eval for CallArgs { impl Eval for ClosureExpr { type Output = Value; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { // The closure's name is defined by its let binding if there's one. let name = self.name().map(Ident::take); // Collect captured variables. let captured = { - let mut visitor = CapturesVisitor::new(&vm.scopes); + let mut visitor = CapturesVisitor::new(scp); visitor.visit(self.as_red()); visitor.finish() }; @@ -503,7 +503,8 @@ impl Eval for ClosureExpr { params.push((name.take(), None)); } ClosureParam::Named(named) => { - params.push((named.name().take(), Some(named.expr().eval(vm)?))); + params + .push((named.name().take(), Some(named.expr().eval(ctx, scp)?))); } ClosureParam::Sink(name) => { if sink.is_some() { @@ -528,10 +529,10 @@ impl Eval for ClosureExpr { impl Eval for WithExpr { type Output = Value; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { let callee = self.callee(); - let func = callee.eval(vm)?.cast::<Func>().at(callee.span())?; - let args = self.args().eval(vm)?; + let func = callee.eval(ctx, scp)?.cast::<Func>().at(callee.span())?; + let args = self.args().eval(ctx, scp)?; Ok(Value::Func(func.with(args))) } } @@ -539,12 +540,12 @@ impl Eval for WithExpr { impl Eval for LetExpr { type Output = Value; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { let value = match self.init() { - Some(expr) => expr.eval(vm)?, + Some(expr) => expr.eval(ctx, scp)?, None => Value::None, }; - vm.scopes.top.def_mut(self.binding().take(), value); + scp.top.def_mut(self.binding().take(), value); Ok(Value::None) } } @@ -552,10 +553,10 @@ impl Eval for LetExpr { impl Eval for SetExpr { type Output = StyleMap; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { let class = self.class(); - let class = class.eval(vm)?.cast::<Class>().at(class.span())?; - let args = self.args().eval(vm)?; + let class = class.eval(ctx, scp)?.cast::<Class>().at(class.span())?; + let args = self.args().eval(ctx, scp)?; class.set(args) } } @@ -563,11 +564,11 @@ impl Eval for SetExpr { impl Eval for ShowExpr { type Output = StyleMap; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { let class = self.class(); - let class = class.eval(vm)?.cast::<Class>().at(class.span())?; + let class = class.eval(ctx, scp)?.cast::<Class>().at(class.span())?; let closure = self.closure(); - let func = closure.eval(vm)?.cast::<Func>().at(closure.span())?; + let func = closure.eval(ctx, scp)?.cast::<Func>().at(closure.span())?; let mut styles = StyleMap::new(); styles.set_recipe(class.id(), func, self.span()); Ok(styles) @@ -577,12 +578,12 @@ impl Eval for ShowExpr { impl Eval for IfExpr { type Output = Value; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { let condition = self.condition(); - if condition.eval(vm)?.cast::<bool>().at(condition.span())? { - self.if_body().eval(vm) + if condition.eval(ctx, scp)?.cast::<bool>().at(condition.span())? { + self.if_body().eval(ctx, scp) } else if let Some(else_body) = self.else_body() { - else_body.eval(vm) + else_body.eval(ctx, scp) } else { Ok(Value::None) } @@ -592,13 +593,13 @@ impl Eval for IfExpr { impl Eval for WhileExpr { type Output = Value; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { let mut output = Value::None; let condition = self.condition(); - while condition.eval(vm)?.cast::<bool>().at(condition.span())? { + while condition.eval(ctx, scp)?.cast::<bool>().at(condition.span())? { let body = self.body(); - let value = body.eval(vm)?; + let value = body.eval(ctx, scp)?; output = ops::join(output, value).at(body.span())?; } @@ -609,27 +610,27 @@ impl Eval for WhileExpr { impl Eval for ForExpr { type Output = Value; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { macro_rules! iter { (for ($($binding:ident => $value:ident),*) in $iter:expr) => {{ let mut output = Value::None; - vm.scopes.enter(); + scp.enter(); #[allow(unused_parens)] for ($($value),*) in $iter { - $(vm.scopes.top.def_mut(&$binding, $value);)* + $(scp.top.def_mut(&$binding, $value);)* - let value = self.body().eval(vm)?; + let value = self.body().eval(ctx, scp)?; output = ops::join(output, value) .at(self.body().span())?; } - vm.scopes.exit(); + scp.exit(); return Ok(output); }}; } - let iter = self.iter().eval(vm)?; + let iter = self.iter().eval(ctx, scp)?; let pattern = self.pattern(); let key = pattern.key().map(Ident::take); let value = pattern.value().take(); @@ -672,21 +673,21 @@ impl Eval for ForExpr { impl Eval for ImportExpr { type Output = Value; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { let span = self.path().span(); - let path = self.path().eval(vm)?.cast::<EcoString>().at(span)?; - let module = import(vm, &path, span)?; + let path = self.path().eval(ctx, scp)?.cast::<EcoString>().at(span)?; + let module = import(ctx, &path, span)?; match self.imports() { Imports::Wildcard => { for (var, slot) in module.scope.iter() { - vm.scopes.top.def_mut(var, slot.read().unwrap().clone()); + scp.top.def_mut(var, slot.read().unwrap().clone()); } } Imports::Items(idents) => { for ident in idents { if let Some(slot) = module.scope.get(&ident) { - vm.scopes.top.def_mut(ident.take(), slot.read().unwrap().clone()); + scp.top.def_mut(ident.take(), slot.read().unwrap().clone()); } else { bail!(ident.span(), "unresolved import"); } @@ -699,40 +700,42 @@ impl Eval for ImportExpr { } impl Eval for IncludeExpr { - type Output = Value; + type Output = Template; - fn eval(&self, vm: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult<Self::Output> { let span = self.path().span(); - let path = self.path().eval(vm)?.cast::<EcoString>().at(span)?; - let module = import(vm, &path, span)?; - Ok(Value::Template(module.template.clone())) + let path = self.path().eval(ctx, scp)?.cast::<EcoString>().at(span)?; + let module = import(ctx, &path, span)?; + Ok(module.template.clone()) } } /// Process an import of a module relative to the current location. -fn import(vm: &mut Vm, path: &str, span: Span) -> TypResult<Module> { +fn import(ctx: &mut Context, path: &str, span: Span) -> TypResult<Module> { // Load the source file. - let full = vm.resolve(path); - let id = vm.sources.load(&full).map_err(|err| { + let full = ctx.resolve(path); + let id = ctx.sources.load(&full).map_err(|err| { Error::boxed(span, match err.kind() { - io::ErrorKind::NotFound => "file not found".into(), + std::io::ErrorKind::NotFound => "file not found".into(), _ => format!("failed to load source file ({})", err), }) })?; // Prevent cyclic importing. - if vm.route.contains(&id) { + if ctx.route.contains(&id) { bail!(span, "cyclic import"); } // Evaluate the file. - vm.evaluate(id).trace(|| Tracepoint::Import, span) + let module = ctx.evaluate(id).trace(|| Tracepoint::Import, span)?; + ctx.deps.extend(module.deps.iter().cloned()); + Ok(module) } impl Eval for BreakExpr { type Output = Value; - fn eval(&self, _: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, _: &mut Context, _: &mut Scopes) -> TypResult<Self::Output> { Err("break is not yet implemented").at(self.span()) } } @@ -740,7 +743,7 @@ impl Eval for BreakExpr { impl Eval for ContinueExpr { type Output = Value; - fn eval(&self, _: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, _: &mut Context, _: &mut Scopes) -> TypResult<Self::Output> { Err("continue is not yet implemented").at(self.span()) } } @@ -748,7 +751,7 @@ impl Eval for ContinueExpr { impl Eval for ReturnExpr { type Output = Value; - fn eval(&self, _: &mut Vm) -> TypResult<Self::Output> { + fn eval(&self, _: &mut Context, _: &mut Scopes) -> TypResult<Self::Output> { Err("return is not yet implemented").at(self.span()) } } @@ -758,25 +761,25 @@ impl Eval for ReturnExpr { /// This only works if the expression is a valid lvalue. pub trait Access { /// Try to access the value. - fn access(&self, vm: &mut Vm, f: Handler) -> TypResult<()>; + fn access(&self, ctx: &mut Context, scp: &mut Scopes, f: Handler) -> TypResult<()>; } /// Process an accessed value. type Handler<'a> = Box<dyn FnOnce(&mut Value) -> TypResult<()> + 'a>; impl Access for Expr { - fn access(&self, vm: &mut Vm, f: Handler) -> TypResult<()> { + fn access(&self, ctx: &mut Context, scp: &mut Scopes, f: Handler) -> TypResult<()> { match self { - Expr::Ident(ident) => ident.access(vm, f), - Expr::Call(call) => call.access(vm, f), + Expr::Ident(ident) => ident.access(ctx, scp, f), + Expr::Call(call) => call.access(ctx, scp, f), _ => bail!(self.span(), "cannot access this expression mutably"), } } } impl Access for Ident { - fn access(&self, vm: &mut Vm, f: Handler) -> TypResult<()> { - match vm.scopes.get(self) { + fn access(&self, _: &mut Context, scp: &mut Scopes, f: Handler) -> TypResult<()> { + match scp.get(self) { Some(slot) => match slot.try_write() { Ok(mut guard) => f(&mut guard), Err(_) => bail!(self.span(), "cannot mutate a constant"), @@ -787,10 +790,11 @@ impl Access for Ident { } impl Access for CallExpr { - fn access(&self, vm: &mut Vm, f: Handler) -> TypResult<()> { - let args = self.args().eval(vm)?; + fn access(&self, ctx: &mut Context, scp: &mut Scopes, f: Handler) -> TypResult<()> { + let args = self.args().eval(ctx, scp)?; self.callee().access( - vm, + ctx, + scp, Box::new(|value| match value { Value::Array(array) => { f(array.get_mut(args.into_index()?).at(self.span())?) diff --git a/src/eval/module.rs b/src/eval/module.rs new file mode 100644 index 00000000..478c76b7 --- /dev/null +++ b/src/eval/module.rs @@ -0,0 +1,20 @@ +use super::{Scope, Template}; +use crate::source::{SourceId, SourceStore}; + +/// An evaluated module, ready for importing or layouting. +#[derive(Debug, Clone)] +pub struct Module { + /// The top-level definitions that were bound in this module. + pub scope: Scope, + /// The module's layoutable contents. + pub template: Template, + /// The source file revisions this module depends on. + pub deps: Vec<(SourceId, usize)>, +} + +impl Module { + /// Whether the module is still valid for the given sources. + pub fn valid(&self, sources: &SourceStore) -> bool { + self.deps.iter().all(|&(id, rev)| rev == sources.get(id).rev()) + } +} diff --git a/src/eval/scope.rs b/src/eval/scope.rs index 0df4c4df..e09d05c8 100644 --- a/src/eval/scope.rs +++ b/src/eval/scope.rs @@ -4,9 +4,10 @@ use std::hash::{Hash, Hasher}; use std::iter; use std::sync::{Arc, RwLock}; -use super::{Args, Class, Construct, Func, Set, Value, Vm}; +use super::{Args, Class, Construct, Func, Set, Value}; use crate::diag::TypResult; use crate::util::EcoString; +use crate::Context; /// A slot where a variable is stored. pub type Slot = Arc<RwLock<Value>>; @@ -86,7 +87,7 @@ impl Scope { pub fn def_func( &mut self, name: &'static str, - func: fn(&mut Vm, &mut Args) -> TypResult<Value>, + func: fn(&mut Context, &mut Args) -> TypResult<Value>, ) { self.def_const(name, Func::native(name, func)); } diff --git a/src/eval/show.rs b/src/eval/show.rs index ac0e2378..b0fb8172 100644 --- a/src/eval/show.rs +++ b/src/eval/show.rs @@ -6,12 +6,12 @@ use std::sync::Arc; use super::{StyleChain, Template}; use crate::diag::TypResult; use crate::util::Prehashed; -use crate::Vm; +use crate::Context; /// A node that can be realized given some styles. pub trait Show { /// Realize the template in the given styles. - fn show(&self, vm: &mut Vm, styles: StyleChain) -> TypResult<Template>; + fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Template>; /// Convert to a packed show node. fn pack(self) -> ShowNode @@ -42,8 +42,8 @@ impl ShowNode { } impl Show for ShowNode { - fn show(&self, vm: &mut Vm, styles: StyleChain) -> TypResult<Template> { - self.0.show(vm, styles) + fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Template> { + self.0.show(ctx, styles) } fn pack(self) -> ShowNode { diff --git a/src/eval/styles.rs b/src/eval/styles.rs index 346eb784..bd1f808f 100644 --- a/src/eval/styles.rs +++ b/src/eval/styles.rs @@ -3,9 +3,10 @@ use std::fmt::{self, Debug, Formatter}; use std::hash::{Hash, Hasher}; use std::sync::Arc; -use super::{Args, Func, Span, Template, Value, Vm}; +use super::{Args, Func, Span, Template, Value}; use crate::diag::{At, TypResult}; use crate::library::{PageNode, ParNode}; +use crate::Context; /// A map of style properties. #[derive(Default, Clone, PartialEq, Hash)] @@ -341,11 +342,6 @@ impl<'a> StyleChain<'a> { *self = self.outer.copied().unwrap_or_default(); } - /// Return the span of a recipe for the given node. - pub(crate) fn recipe_span(self, node: TypeId) -> Option<Span> { - self.recipes(node).next().map(|recipe| recipe.span) - } - /// Return the chain, but without the last link if that one contains only /// scoped styles. This is a hack. pub(crate) fn unscoped(mut self, node: TypeId) -> Self { @@ -415,12 +411,12 @@ impl<'a> StyleChain<'a> { pub fn show( self, node: &dyn Any, - vm: &mut Vm, + ctx: &mut Context, values: impl IntoIterator<Item = Value>, ) -> TypResult<Option<Template>> { Ok(if let Some(recipe) = self.recipes(node.type_id()).next() { let args = Args::from_values(recipe.span, values); - Some(recipe.func.call(vm, args)?.cast().at(recipe.span)?) + Some(recipe.func.call(ctx, args)?.cast().at(recipe.span)?) } else { None }) diff --git a/src/eval/template.rs b/src/eval/template.rs index b4e3c76d..a9e1262f 100644 --- a/src/eval/template.rs +++ b/src/eval/template.rs @@ -1,7 +1,6 @@ use std::fmt::Debug; use std::hash::Hash; use std::iter::Sum; -use std::mem; use std::ops::{Add, AddAssign}; use typed_arena::Arena; @@ -169,21 +168,23 @@ impl Template { } /// Layout this template into a collection of pages. - pub fn layout_pages(&self, vm: &mut Vm) -> TypResult<Vec<Arc<Frame>>> { + pub fn layout(&self, ctx: &mut Context) -> TypResult<Vec<Arc<Frame>>> { let sya = Arena::new(); let tpa = Arena::new(); + let styles = ctx.styles.clone(); + let styles = StyleChain::new(&styles); + let mut builder = Builder::new(&sya, &tpa, true); - let styles = StyleChain::new(vm.styles); - builder.process(vm, self, styles)?; - builder.finish(vm, styles)?; + builder.process(ctx, self, styles)?; + builder.finish(ctx, styles)?; let mut frames = vec![]; let (pages, shared) = builder.pages.unwrap().finish(); for (page, map) in pages.iter() { let number = 1 + frames.len(); - frames.extend(page.layout(vm, number, map.chain(&shared))?); + frames.extend(page.layout(ctx, number, map.chain(&shared))?); } Ok(frames) @@ -224,7 +225,7 @@ impl Add for Template { impl AddAssign for Template { fn add_assign(&mut self, rhs: Self) { - *self = mem::take(self) + rhs; + *self = std::mem::take(self) + rhs; } } @@ -237,7 +238,7 @@ impl Sum for Template { impl Layout for Template { fn layout( &self, - vm: &mut Vm, + ctx: &mut Context, regions: &Regions, styles: StyleChain, ) -> TypResult<Vec<Arc<Frame>>> { @@ -245,11 +246,11 @@ impl Layout for Template { let tpa = Arena::new(); let mut builder = Builder::new(&sya, &tpa, false); - builder.process(vm, self, styles)?; - builder.finish(vm, styles)?; + builder.process(ctx, self, styles)?; + builder.finish(ctx, styles)?; let (flow, shared) = builder.flow.finish(); - FlowNode(flow).layout(vm, regions, shared) + FlowNode(flow).layout(ctx, regions, shared) } fn pack(self) -> LayoutNode { @@ -295,7 +296,7 @@ impl<'a> Builder<'a> { /// Process a template. fn process( &mut self, - vm: &mut Vm, + ctx: &mut Context, template: &'a Template, styles: StyleChain<'a>, ) -> TypResult<()> { @@ -323,7 +324,7 @@ impl<'a> Builder<'a> { builder.items.push(item.clone()); return Ok(()); } - _ => self.finish_list(vm)?, + _ => self.finish_list(ctx)?, } } @@ -394,25 +395,19 @@ impl<'a> Builder<'a> { }); } Template::Pagebreak => { - self.finish_page(vm, true, true, styles)?; + self.finish_page(ctx, true, true, styles)?; } Template::Page(page) => { - self.finish_page(vm, false, false, styles)?; + self.finish_page(ctx, false, false, styles)?; if let Some(pages) = &mut self.pages { pages.push(page.clone(), styles); } } Template::Show(node) => { let id = node.id(); - if vm.rules.contains(&id) { - let span = styles.recipe_span(id).unwrap(); - return Err("show rule is recursive").at(span)?; - } - vm.rules.push(id); - let template = node.show(vm, styles)?; + let template = node.show(ctx, styles)?; let stored = self.tpa.alloc(template); - self.process(vm, stored, styles.unscoped(id))?; - vm.rules.pop(); + self.process(ctx, stored, styles.unscoped(id))?; } Template::Styled(styled) => { let (sub, map) = styled.as_ref(); @@ -422,17 +417,17 @@ impl<'a> Builder<'a> { let interruption = map.interruption(); match interruption { Some(Interruption::Page) => { - self.finish_page(vm, false, true, styles)? + self.finish_page(ctx, false, true, styles)? } Some(Interruption::Par) => self.finish_par(styles), None => {} } - self.process(vm, sub, styles)?; + self.process(ctx, sub, styles)?; match interruption { Some(Interruption::Page) => { - self.finish_page(vm, true, false, styles)? + self.finish_page(ctx, true, false, styles)? } Some(Interruption::Par) => self.finish_par(styles), None => {} @@ -440,7 +435,7 @@ impl<'a> Builder<'a> { } Template::Sequence(seq) => { for sub in seq.iter() { - self.process(vm, sub, styles)?; + self.process(ctx, sub, styles)?; } } } @@ -450,7 +445,7 @@ impl<'a> Builder<'a> { /// Finish the currently built paragraph. fn finish_par(&mut self, styles: StyleChain<'a>) { - let (par, shared) = mem::take(&mut self.par).finish(); + let (par, shared) = std::mem::take(&mut self.par).finish(); if !par.is_empty() { let node = ParNode(par).pack(); self.flow.supportive(FlowChild::Node(node), shared); @@ -459,7 +454,7 @@ impl<'a> Builder<'a> { } /// Finish the currently built list. - fn finish_list(&mut self, vm: &mut Vm) -> TypResult<()> { + fn finish_list(&mut self, ctx: &mut Context) -> TypResult<()> { let ListBuilder { styles, kind, items, wide, staged } = match self.list.take() { Some(list) => list, None => return Ok(()), @@ -471,9 +466,9 @@ impl<'a> Builder<'a> { }; let stored = self.tpa.alloc(template); - self.process(vm, stored, styles)?; + self.process(ctx, stored, styles)?; for (template, styles) in staged { - self.process(vm, template, styles)?; + self.process(ctx, template, styles)?; } Ok(()) @@ -482,15 +477,15 @@ impl<'a> Builder<'a> { /// Finish the currently built page run. fn finish_page( &mut self, - vm: &mut Vm, + ctx: &mut Context, keep_last: bool, keep_next: bool, styles: StyleChain<'a>, ) -> TypResult<()> { - self.finish_list(vm)?; + self.finish_list(ctx)?; self.finish_par(styles); if let Some(pages) = &mut self.pages { - let (flow, shared) = mem::take(&mut self.flow).finish(); + let (flow, shared) = std::mem::take(&mut self.flow).finish(); if !flow.is_empty() || (keep_last && self.keep_next) { let styles = if flow.is_empty() { styles } else { shared }; let node = PageNode(FlowNode(flow).pack()); @@ -502,8 +497,8 @@ impl<'a> Builder<'a> { } /// Finish everything. - fn finish(&mut self, vm: &mut Vm, styles: StyleChain<'a>) -> TypResult<()> { - self.finish_page(vm, true, false, styles) + fn finish(&mut self, ctx: &mut Context, styles: StyleChain<'a>) -> TypResult<()> { + self.finish_page(ctx, true, false, styles) } } |
