diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-02-17 15:47:54 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-02-17 17:32:56 +0100 |
| commit | c5e67af22bd6242366819879be84c10c4dd135be (patch) | |
| tree | d857b99b26401d1b3b74c4cebacbf086c25bef40 /src/library | |
| parent | 3d965ae6a479636a13b2e2f2344e8d97bedece1f (diff) | |
Merge eval and layout contexts into `Vm`
Diffstat (limited to 'src/library')
| -rw-r--r-- | src/library/align.rs | 6 | ||||
| -rw-r--r-- | src/library/columns.rs | 10 | ||||
| -rw-r--r-- | src/library/container.rs | 4 | ||||
| -rw-r--r-- | src/library/deco.rs | 2 | ||||
| -rw-r--r-- | src/library/flow.rs | 15 | ||||
| -rw-r--r-- | src/library/grid.rs | 54 | ||||
| -rw-r--r-- | src/library/heading.rs | 2 | ||||
| -rw-r--r-- | src/library/hide.rs | 6 | ||||
| -rw-r--r-- | src/library/image.rs | 10 | ||||
| -rw-r--r-- | src/library/link.rs | 2 | ||||
| -rw-r--r-- | src/library/list.rs | 2 | ||||
| -rw-r--r-- | src/library/math.rs | 2 | ||||
| -rw-r--r-- | src/library/mod.rs | 7 | ||||
| -rw-r--r-- | src/library/pad.rs | 6 | ||||
| -rw-r--r-- | src/library/page.rs | 8 | ||||
| -rw-r--r-- | src/library/par.rs | 46 | ||||
| -rw-r--r-- | src/library/place.rs | 6 | ||||
| -rw-r--r-- | src/library/raw.rs | 2 | ||||
| -rw-r--r-- | src/library/shape.rs | 8 | ||||
| -rw-r--r-- | src/library/spacing.rs | 4 | ||||
| -rw-r--r-- | src/library/stack.rs | 15 | ||||
| -rw-r--r-- | src/library/table.rs | 2 | ||||
| -rw-r--r-- | src/library/text.rs | 6 | ||||
| -rw-r--r-- | src/library/transform.rs | 6 | ||||
| -rw-r--r-- | src/library/utility.rs | 44 |
25 files changed, 131 insertions, 144 deletions
diff --git a/src/library/align.rs b/src/library/align.rs index 1fb91138..5b50937e 100644 --- a/src/library/align.rs +++ b/src/library/align.rs @@ -14,7 +14,7 @@ pub struct AlignNode { #[class] impl AlignNode { - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { let aligns: Spec<_> = args.find()?.unwrap_or_default(); let body: LayoutNode = args.expect("body")?; Ok(Template::block(body.aligned(aligns))) @@ -24,7 +24,7 @@ impl AlignNode { impl Layout for AlignNode { fn layout( &self, - ctx: &mut LayoutContext, + vm: &mut Vm, regions: &Regions, styles: StyleChain, ) -> Vec<Constrained<Arc<Frame>>> { @@ -39,7 +39,7 @@ impl Layout for AlignNode { } // Layout the child. - let mut frames = self.child.layout(ctx, &pod, passed.chain(&styles)); + let mut frames = self.child.layout(vm, &pod, passed.chain(&styles)); for ((current, base), Constrained { item: frame, cts }) in regions.iter().zip(&mut frames) diff --git a/src/library/columns.rs b/src/library/columns.rs index 98989c5a..61da6177 100644 --- a/src/library/columns.rs +++ b/src/library/columns.rs @@ -18,7 +18,7 @@ impl ColumnsNode { /// The size of the gutter space between each column. pub const GUTTER: Linear = Relative::new(0.04).into(); - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { Ok(Template::block(Self { columns: args.expect("column count")?, child: args.expect("body")?, @@ -29,14 +29,14 @@ impl ColumnsNode { impl Layout for ColumnsNode { fn layout( &self, - ctx: &mut LayoutContext, + vm: &mut Vm, regions: &Regions, styles: StyleChain, ) -> Vec<Constrained<Arc<Frame>>> { // Separating the infinite space into infinite columns does not make // much sense. if regions.current.x.is_infinite() { - return self.child.layout(ctx, regions, styles); + return self.child.layout(vm, regions, styles); } // Determine the width of the gutter and each column. @@ -59,7 +59,7 @@ impl Layout for ColumnsNode { }; // Layout the children. - let mut frames = self.child.layout(ctx, &pod, styles).into_iter(); + let mut frames = self.child.layout(vm, &pod, styles).into_iter(); let dir = styles.get(ParNode::DIR); let total_regions = (frames.len() as f32 / columns as f32).ceil() as usize; @@ -111,7 +111,7 @@ pub struct ColbreakNode; #[class] impl ColbreakNode { - fn construct(_: &mut EvalContext, _: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, _: &mut Args) -> TypResult<Template> { Ok(Template::Colbreak) } } diff --git a/src/library/container.rs b/src/library/container.rs index 382be262..fafa7103 100644 --- a/src/library/container.rs +++ b/src/library/container.rs @@ -7,7 +7,7 @@ pub struct BoxNode; #[class] impl BoxNode { - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { let width = args.named("width")?; let height = args.named("height")?; let body: LayoutNode = args.find()?.unwrap_or_default(); @@ -20,7 +20,7 @@ pub struct BlockNode; #[class] impl BlockNode { - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { Ok(Template::Block(args.find()?.unwrap_or_default())) } } diff --git a/src/library/deco.rs b/src/library/deco.rs index 5e438d54..92fcf09f 100644 --- a/src/library/deco.rs +++ b/src/library/deco.rs @@ -26,7 +26,7 @@ impl<const L: DecoLine> DecoNode<L> { /// with the glyphs. Does not apply to strikethrough. pub const EVADE: bool = true; - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { Ok(Template::show(Self(args.expect::<Template>("body")?))) } } diff --git a/src/library/flow.rs b/src/library/flow.rs index ca554033..95469b65 100644 --- a/src/library/flow.rs +++ b/src/library/flow.rs @@ -28,7 +28,7 @@ pub enum FlowChild { impl Layout for FlowNode { fn layout( &self, - ctx: &mut LayoutContext, + vm: &mut Vm, regions: &Regions, styles: StyleChain, ) -> Vec<Constrained<Arc<Frame>>> { @@ -56,7 +56,7 @@ impl Layout for FlowNode { layouter.layout_spacing(*kind); } FlowChild::Node(ref node) => { - layouter.layout_node(ctx, node, styles); + layouter.layout_node(vm, node, styles); } } } @@ -161,12 +161,7 @@ impl FlowLayouter { } /// Layout a node. - pub fn layout_node( - &mut self, - ctx: &mut LayoutContext, - node: &LayoutNode, - styles: StyleChain, - ) { + pub fn layout_node(&mut self, vm: &mut Vm, node: &LayoutNode, styles: StyleChain) { // Don't even try layouting into a full region. if self.regions.is_full() { self.finish_region(); @@ -176,7 +171,7 @@ impl FlowLayouter { // aligned later. if let Some(placed) = node.downcast::<PlaceNode>() { if placed.out_of_flow() { - let frame = node.layout(ctx, &self.regions, styles).remove(0); + let frame = node.layout(vm, &self.regions, styles).remove(0); self.items.push(FlowItem::Placed(frame.item)); return; } @@ -193,7 +188,7 @@ impl FlowLayouter { .unwrap_or(Align::Top), ); - let frames = node.layout(ctx, &self.regions, styles); + let frames = node.layout(vm, &self.regions, styles); let len = frames.len(); for (i, frame) in frames.into_iter().enumerate() { // Grow our size, shrink the region and save the frame for later. diff --git a/src/library/grid.rs b/src/library/grid.rs index c9904a5f..78ac375f 100644 --- a/src/library/grid.rs +++ b/src/library/grid.rs @@ -15,7 +15,7 @@ pub struct GridNode { #[class] impl GridNode { - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { let columns = args.named("columns")?.unwrap_or_default(); let rows = args.named("rows")?.unwrap_or_default(); let base_gutter: Vec<TrackSizing> = args.named("gutter")?.unwrap_or_default(); @@ -35,7 +35,7 @@ impl GridNode { impl Layout for GridNode { fn layout( &self, - ctx: &mut LayoutContext, + vm: &mut Vm, regions: &Regions, styles: StyleChain, ) -> Vec<Constrained<Arc<Frame>>> { @@ -49,7 +49,7 @@ impl Layout for GridNode { ); // Measure the columsna nd layout the grid row-by-row. - layouter.layout(ctx) + layouter.layout(vm) } } @@ -205,19 +205,19 @@ impl<'a> GridLayouter<'a> { } /// Determines the columns sizes and then layouts the grid row-by-row. - pub fn layout(mut self, ctx: &mut LayoutContext) -> Vec<Constrained<Arc<Frame>>> { - self.measure_columns(ctx); + pub fn layout(mut self, vm: &mut Vm) -> Vec<Constrained<Arc<Frame>>> { + self.measure_columns(vm); for y in 0 .. self.rows.len() { // Skip to next region if current one is full, but only for content // rows, not for gutter rows. if y % 2 == 0 && self.regions.is_full() { - self.finish_region(ctx); + self.finish_region(vm); } match self.rows[y] { - TrackSizing::Auto => self.layout_auto_row(ctx, y), - TrackSizing::Linear(v) => self.layout_linear_row(ctx, v, y), + TrackSizing::Auto => self.layout_auto_row(vm, y), + TrackSizing::Linear(v) => self.layout_linear_row(vm, v, y), TrackSizing::Fractional(v) => { self.cts.exact.y = Some(self.full); self.lrows.push(Row::Fr(v, y)); @@ -226,12 +226,12 @@ impl<'a> GridLayouter<'a> { } } - self.finish_region(ctx); + self.finish_region(vm); self.finished } /// Determine all column sizes. - fn measure_columns(&mut self, ctx: &mut LayoutContext) { + fn measure_columns(&mut self, vm: &mut Vm) { enum Case { /// The column sizing is only determined by specified linear sizes. PurelyLinear, @@ -277,7 +277,7 @@ impl<'a> GridLayouter<'a> { let available = self.regions.current.x - linear; if available >= Length::zero() { // Determine size of auto columns. - let (auto, count) = self.measure_auto_columns(ctx, available); + let (auto, count) = self.measure_auto_columns(vm, available); // If there is remaining space, distribute it to fractional columns, // otherwise shrink auto columns. @@ -313,7 +313,7 @@ impl<'a> GridLayouter<'a> { /// Measure the size that is available to auto columns. fn measure_auto_columns( &mut self, - ctx: &mut LayoutContext, + vm: &mut Vm, available: Length, ) -> (Length, usize) { let mut auto = Length::zero(); @@ -340,7 +340,7 @@ impl<'a> GridLayouter<'a> { pod.base.y = v.resolve(self.regions.base.y); } - let frame = node.layout(ctx, &pod, self.styles).remove(0).item; + let frame = node.layout(vm, &pod, self.styles).remove(0).item; resolved.set_max(frame.size.x); } } @@ -394,7 +394,7 @@ impl<'a> GridLayouter<'a> { /// Layout a row with automatic height. Such a row may break across multiple /// regions. - fn layout_auto_row(&mut self, ctx: &mut LayoutContext, y: usize) { + fn layout_auto_row(&mut self, vm: &mut Vm, y: usize) { let mut resolved: Vec<Length> = vec![]; // Determine the size for each region of the row. @@ -409,7 +409,7 @@ impl<'a> GridLayouter<'a> { } let mut sizes = node - .layout(ctx, &pod, self.styles) + .layout(vm, &pod, self.styles) .into_iter() .map(|frame| frame.item.size.y); @@ -432,7 +432,7 @@ impl<'a> GridLayouter<'a> { // Layout into a single region. if let &[first] = resolved.as_slice() { - let frame = self.layout_single_row(ctx, first, y); + let frame = self.layout_single_row(vm, first, y); self.push_row(frame); return; } @@ -449,28 +449,28 @@ impl<'a> GridLayouter<'a> { } // Layout into multiple regions. - let frames = self.layout_multi_row(ctx, &resolved, y); + let frames = self.layout_multi_row(vm, &resolved, y); let len = frames.len(); for (i, frame) in frames.into_iter().enumerate() { self.push_row(frame); if i + 1 < len { self.cts.exact.y = Some(self.full); - self.finish_region(ctx); + self.finish_region(vm); } } } /// Layout a row with linear height. Such a row cannot break across multiple /// regions, but it may force a region break. - fn layout_linear_row(&mut self, ctx: &mut LayoutContext, v: Linear, y: usize) { + fn layout_linear_row(&mut self, vm: &mut Vm, v: Linear, y: usize) { let resolved = v.resolve(self.regions.base.y); - let frame = self.layout_single_row(ctx, resolved, y); + let frame = self.layout_single_row(vm, resolved, y); // Skip to fitting region. let height = frame.size.y; while !self.regions.current.y.fits(height) && !self.regions.in_last() { self.cts.max.y = Some(self.used.y + height); - self.finish_region(ctx); + self.finish_region(vm); // Don't skip multiple regions for gutter and don't push a row. if y % 2 == 1 { @@ -484,7 +484,7 @@ impl<'a> GridLayouter<'a> { /// Layout a row with fixed height and return its frame. fn layout_single_row( &self, - ctx: &mut LayoutContext, + vm: &mut Vm, height: Length, y: usize, ) -> Frame { @@ -502,7 +502,7 @@ impl<'a> GridLayouter<'a> { .select(self.regions.base, size); let pod = Regions::one(size, base, Spec::splat(true)); - let frame = node.layout(ctx, &pod, self.styles).remove(0); + let frame = node.layout(vm, &pod, self.styles).remove(0); output.push_frame(pos, frame.item); } @@ -515,7 +515,7 @@ impl<'a> GridLayouter<'a> { /// Layout a row spanning multiple regions. fn layout_multi_row( &self, - ctx: &mut LayoutContext, + vm: &mut Vm, heights: &[Length], y: usize, ) -> Vec<Frame> { @@ -542,7 +542,7 @@ impl<'a> GridLayouter<'a> { } // Push the layouted frames into the individual output frames. - let frames = node.layout(ctx, &pod, self.styles); + let frames = node.layout(vm, &pod, self.styles); for (output, frame) in outputs.iter_mut().zip(frames) { output.push_frame(pos, frame.item); } @@ -562,7 +562,7 @@ impl<'a> GridLayouter<'a> { } /// Finish rows for one region. - fn finish_region(&mut self, ctx: &mut LayoutContext) { + fn finish_region(&mut self, vm: &mut Vm) { // Determine the size of the grid in this region, expanding fully if // there are fr rows. let mut size = self.used; @@ -584,7 +584,7 @@ impl<'a> GridLayouter<'a> { Row::Fr(v, y) => { let remaining = self.full - self.used.y; let height = v.resolve(self.fr, remaining); - self.layout_single_row(ctx, height, y) + self.layout_single_row(vm, height, y) } }; diff --git a/src/library/heading.rs b/src/library/heading.rs index 00a48021..2123116b 100644 --- a/src/library/heading.rs +++ b/src/library/heading.rs @@ -34,7 +34,7 @@ impl HeadingNode { /// The extra padding below the heading. pub const BELOW: Length = Length::zero(); - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { Ok(Template::show(Self { body: args.expect("body")?, level: args.named("level")?.unwrap_or(1), diff --git a/src/library/hide.rs b/src/library/hide.rs index 72d8e52b..230300d2 100644 --- a/src/library/hide.rs +++ b/src/library/hide.rs @@ -8,7 +8,7 @@ pub struct HideNode(pub LayoutNode); #[class] impl HideNode { - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { Ok(Template::inline(Self(args.expect("body")?))) } } @@ -16,11 +16,11 @@ impl HideNode { impl Layout for HideNode { fn layout( &self, - ctx: &mut LayoutContext, + vm: &mut Vm, regions: &Regions, styles: StyleChain, ) -> Vec<Constrained<Arc<Frame>>> { - let mut frames = self.0.layout(ctx, regions, styles); + let mut frames = self.0.layout(vm, regions, styles); // Clear the frames. for Constrained { item: frame, .. } in &mut frames { diff --git a/src/library/image.rs b/src/library/image.rs index 59e30364..5527fbdc 100644 --- a/src/library/image.rs +++ b/src/library/image.rs @@ -14,10 +14,10 @@ impl ImageNode { /// How the image should adjust itself to a given area. pub const FIT: ImageFit = ImageFit::Cover; - fn construct(ctx: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(vm: &mut Vm, args: &mut Args) -> TypResult<Template> { let path = args.expect::<Spanned<EcoString>>("path to image file")?; - let full = ctx.make_path(&path.v); - let id = ctx.images.load(&full).map_err(|err| { + let full = vm.resolve(&path.v); + let id = vm.images.load(&full).map_err(|err| { Error::boxed(path.span, match err.kind() { std::io::ErrorKind::NotFound => "file not found".into(), _ => format!("failed to load image ({})", err), @@ -36,11 +36,11 @@ impl ImageNode { impl Layout for ImageNode { fn layout( &self, - ctx: &mut LayoutContext, + vm: &mut Vm, regions: &Regions, styles: StyleChain, ) -> Vec<Constrained<Arc<Frame>>> { - let img = ctx.images.get(self.0); + let img = vm.images.get(self.0); let pxw = img.width() as f64; let pxh = img.height() as f64; let px_ratio = pxw / pxh; diff --git a/src/library/link.rs b/src/library/link.rs index 42c630f6..58c7e550 100644 --- a/src/library/link.rs +++ b/src/library/link.rs @@ -21,7 +21,7 @@ impl LinkNode { /// Whether to underline link. pub const UNDERLINE: bool = true; - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { let url = args.expect::<EcoString>("url")?; let body = args.find()?.unwrap_or_else(|| { let mut text = url.as_str(); diff --git a/src/library/list.rs b/src/library/list.rs index e07177f4..7f76a178 100644 --- a/src/library/list.rs +++ b/src/library/list.rs @@ -19,7 +19,7 @@ impl<const L: Labelling> ListNode<L> { /// The space between the label and the body of each item. pub const BODY_INDENT: Linear = Relative::new(0.5).into(); - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { Ok(args .all()? .into_iter() diff --git a/src/library/math.rs b/src/library/math.rs index c75cdea8..29367cd5 100644 --- a/src/library/math.rs +++ b/src/library/math.rs @@ -13,7 +13,7 @@ pub struct MathNode { #[class] impl MathNode { - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { Ok(Template::show(Self { formula: args.expect("formula")?, display: args.named("display")?.unwrap_or(false), diff --git a/src/library/mod.rs b/src/library/mod.rs index db173daf..d90c96da 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -64,16 +64,17 @@ pub mod prelude { pub use crate::diag::{At, TypResult}; pub use crate::eval::{ - Args, Construct, EvalContext, Merge, Property, Scope, Set, Show, ShowNode, Smart, - StyleChain, StyleMap, StyleVec, Template, Value, + Args, Construct, Merge, Property, Scope, Set, Show, ShowNode, Smart, StyleChain, + StyleMap, StyleVec, Template, Value, }; pub use crate::frame::*; pub use crate::geom::*; pub use crate::layout::{ - Constrain, Constrained, Constraints, Layout, LayoutContext, LayoutNode, Regions, + Constrain, Constrained, Constraints, Layout, LayoutNode, Regions, }; pub use crate::syntax::{Span, Spanned}; pub use crate::util::{EcoString, OptionExt}; + pub use crate::Vm; } use prelude::*; diff --git a/src/library/pad.rs b/src/library/pad.rs index 684e1172..84e83939 100644 --- a/src/library/pad.rs +++ b/src/library/pad.rs @@ -13,7 +13,7 @@ pub struct PadNode { #[class] impl PadNode { - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { let all = args.find()?; let left = args.named("left")?; let top = args.named("top")?; @@ -34,13 +34,13 @@ impl PadNode { impl Layout for PadNode { fn layout( &self, - ctx: &mut LayoutContext, + vm: &mut Vm, regions: &Regions, styles: StyleChain, ) -> Vec<Constrained<Arc<Frame>>> { // Layout child into padded regions. let pod = regions.map(|size| shrink(size, self.padding)); - let mut frames = self.child.layout(ctx, &pod, styles); + let mut frames = self.child.layout(vm, &pod, styles); for ((current, base), Constrained { item: frame, cts }) in regions.iter().zip(&mut frames) diff --git a/src/library/page.rs b/src/library/page.rs index 7f0f7332..155f60dd 100644 --- a/src/library/page.rs +++ b/src/library/page.rs @@ -31,7 +31,7 @@ impl PageNode { /// How many columns the page has. pub const COLUMNS: NonZeroUsize = NonZeroUsize::new(1).unwrap(); - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { Ok(Template::Page(Self(args.expect("body")?))) } @@ -60,7 +60,7 @@ impl PageNode { impl PageNode { /// Layout the page run into a sequence of frames, one per page. - pub fn layout(&self, ctx: &mut LayoutContext, styles: StyleChain) -> Vec<Arc<Frame>> { + pub fn layout(&self, vm: &mut Vm, styles: StyleChain) -> Vec<Arc<Frame>> { // When one of the lengths is infinite the page fits its content along // that axis. let width = styles.get(Self::WIDTH).unwrap_or(Length::inf()); @@ -104,7 +104,7 @@ impl PageNode { let expand = size.map(Length::is_finite); let regions = Regions::repeat(size, size, expand); child - .layout(ctx, ®ions, styles) + .layout(vm, ®ions, styles) .into_iter() .map(|c| c.item) .collect() @@ -124,7 +124,7 @@ pub struct PagebreakNode; #[class] impl PagebreakNode { - fn construct(_: &mut EvalContext, _: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, _: &mut Args) -> TypResult<Template> { Ok(Template::Pagebreak) } } diff --git a/src/library/par.rs b/src/library/par.rs index 2a4b4d08..02633612 100644 --- a/src/library/par.rs +++ b/src/library/par.rs @@ -36,7 +36,7 @@ impl ParNode { /// The extra spacing between paragraphs (dependent on scaled font size). pub const SPACING: Linear = Relative::new(0.55).into(); - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { // The paragraph constructor is special: It doesn't create a paragraph // since that happens automatically through markup. Instead, it just // lifts the passed body to the block level so that it won't merge with @@ -82,7 +82,7 @@ impl ParNode { impl Layout for ParNode { fn layout( &self, - ctx: &mut LayoutContext, + vm: &mut Vm, regions: &Regions, styles: StyleChain, ) -> Vec<Constrained<Arc<Frame>>> { @@ -95,10 +95,10 @@ impl Layout for ParNode { // Prepare paragraph layout by building a representation on which we can // do line breaking without layouting each and every line from scratch. - let layouter = ParLayouter::new(self, ctx, regions, &styles, bidi); + let layouter = ParLayouter::new(self, vm, regions, &styles, bidi); // Find suitable linebreaks. - layouter.layout(ctx, regions.clone()) + layouter.layout(vm, regions.clone()) } } @@ -167,7 +167,7 @@ pub struct ParbreakNode; #[class] impl ParbreakNode { - fn construct(_: &mut EvalContext, _: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, _: &mut Args) -> TypResult<Template> { Ok(Template::Parbreak) } } @@ -177,7 +177,7 @@ pub struct LinebreakNode; #[class] impl LinebreakNode { - fn construct(_: &mut EvalContext, _: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, _: &mut Args) -> TypResult<Template> { Ok(Template::Linebreak) } } @@ -216,7 +216,7 @@ impl<'a> ParLayouter<'a> { /// Prepare initial shaped text and layouted children. fn new( par: &'a ParNode, - ctx: &mut LayoutContext, + vm: &mut Vm, regions: &Regions, styles: &'a StyleChain<'a>, bidi: BidiInfo<'a>, @@ -236,7 +236,7 @@ impl<'a> ParLayouter<'a> { cursor += count; let subrange = start .. cursor; let text = &bidi.text[subrange.clone()]; - let shaped = shape(ctx.fonts, text, styles, level.dir()); + let shaped = shape(vm.fonts, text, styles, level.dir()); items.push(ParItem::Text(shaped)); ranges.push(subrange); } @@ -255,7 +255,7 @@ impl<'a> ParLayouter<'a> { ParChild::Node(node) => { let size = Size::new(regions.current.x, regions.base.y); let pod = Regions::one(size, regions.base, Spec::splat(false)); - let frame = node.layout(ctx, &pod, styles).remove(0); + let frame = node.layout(vm, &pod, styles).remove(0); items.push(ParItem::Frame(Arc::take(frame.item))); ranges.push(range); } @@ -270,11 +270,7 @@ impl<'a> ParLayouter<'a> { } /// Find first-fit line breaks and build the paragraph. - fn layout( - self, - ctx: &mut LayoutContext, - regions: Regions, - ) -> Vec<Constrained<Arc<Frame>>> { + fn layout(self, vm: &mut Vm, regions: Regions) -> Vec<Constrained<Arc<Frame>>> { let mut stack = LineStack::new(self.leading, regions); // The current line attempt. @@ -288,7 +284,7 @@ impl<'a> ParLayouter<'a> { // TODO: Provide line break opportunities on alignment changes. for (end, mandatory) in LineBreakIterator::new(self.bidi.text) { // Compute the line and its size. - let mut line = LineLayout::new(ctx, &self, start .. end); + let mut line = LineLayout::new(vm, &self, start .. end); // If the line doesn't fit anymore, we push the last fitting attempt // into the stack and rebuild the line from its end. The resulting @@ -318,7 +314,7 @@ impl<'a> ParLayouter<'a> { stack.push(last_line); stack.cts.min.y = Some(stack.size.y); start = last_end; - line = LineLayout::new(ctx, &self, start .. end); + line = LineLayout::new(vm, &self, start .. end); } } } @@ -335,7 +331,7 @@ impl<'a> ParLayouter<'a> { // below. let too_large = stack.size.y + self.leading + line.size.y; stack.cts.max.y.set_min(too_large); - stack.finish_region(ctx); + stack.finish_region(vm); } // If the line does not fit horizontally or we have a mandatory @@ -350,7 +346,7 @@ impl<'a> ParLayouter<'a> { // If there is a trailing line break at the end of the // paragraph, we want to force an empty line. if mandatory && end == self.bidi.text.len() { - let line = LineLayout::new(ctx, &self, end .. end); + let line = LineLayout::new(vm, &self, end .. end); if stack.regions.current.y.fits(line.size.y) { stack.push(line); } @@ -370,7 +366,7 @@ impl<'a> ParLayouter<'a> { stack.cts.min.y = Some(stack.size.y); } - stack.finish(ctx) + stack.finish(vm) } /// Find the index of the item whose range contains the `text_offset`. @@ -408,7 +404,7 @@ struct LineLayout<'a> { impl<'a> LineLayout<'a> { /// Create a line which spans the given range. - fn new(ctx: &mut LayoutContext, par: &'a ParLayouter<'a>, mut line: Range) -> Self { + fn new(vm: &mut Vm, par: &'a ParLayouter<'a>, mut line: Range) -> Self { // Find the items which bound the text range. let last_idx = par.find(line.end.saturating_sub(1)).unwrap(); let first_idx = if line.is_empty() { @@ -438,7 +434,7 @@ impl<'a> LineLayout<'a> { // empty string. if !range.is_empty() || rest.is_empty() { // Reshape that part. - let reshaped = shaped.reshape(ctx.fonts, range); + let reshaped = shaped.reshape(vm.fonts, range); last = Some(ParItem::Text(reshaped)); } @@ -459,7 +455,7 @@ impl<'a> LineLayout<'a> { // Reshape if necessary. if range.len() < shaped.text.len() { if !range.is_empty() { - let reshaped = shaped.reshape(ctx.fonts, range); + let reshaped = shaped.reshape(vm.fonts, range); first = Some(ParItem::Text(reshaped)); } @@ -504,7 +500,7 @@ impl<'a> LineLayout<'a> { } /// Build the line's frame. - fn build(&self, ctx: &LayoutContext, width: Length) -> Frame { + fn build(&self, ctx: &Vm, width: Length) -> Frame { let size = Size::new(self.size.x.max(width), self.size.y); let remaining = size.x - self.size.x; @@ -622,7 +618,7 @@ impl<'a> LineStack<'a> { } /// Finish the frame for one region. - fn finish_region(&mut self, ctx: &LayoutContext) { + fn finish_region(&mut self, ctx: &Vm) { if self.regions.expand.x || self.fractional { self.size.x = self.regions.current.x; self.cts.exact.x = Some(self.regions.current.x); @@ -653,7 +649,7 @@ impl<'a> LineStack<'a> { } /// Finish the last region and return the built frames. - fn finish(mut self, ctx: &LayoutContext) -> Vec<Constrained<Arc<Frame>>> { + fn finish(mut self, ctx: &Vm) -> Vec<Constrained<Arc<Frame>>> { self.finish_region(ctx); self.finished } diff --git a/src/library/place.rs b/src/library/place.rs index 52bbeb21..c2c9ac25 100644 --- a/src/library/place.rs +++ b/src/library/place.rs @@ -9,7 +9,7 @@ pub struct PlaceNode(pub LayoutNode); #[class] impl PlaceNode { - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { let aligns = args.find()?.unwrap_or(Spec::with_x(Some(Align::Left))); let tx = args.named("dx")?.unwrap_or_default(); let ty = args.named("dy")?.unwrap_or_default(); @@ -23,7 +23,7 @@ impl PlaceNode { impl Layout for PlaceNode { fn layout( &self, - ctx: &mut LayoutContext, + vm: &mut Vm, regions: &Regions, styles: StyleChain, ) -> Vec<Constrained<Arc<Frame>>> { @@ -37,7 +37,7 @@ impl Layout for PlaceNode { Regions::one(regions.base, regions.base, expand) }; - let mut frames = self.0.layout(ctx, &pod, styles); + let mut frames = self.0.layout(vm, &pod, styles); let Constrained { item: frame, cts } = &mut frames[0]; // If expansion is off, zero all sizes so that we don't take up any diff --git a/src/library/raw.rs b/src/library/raw.rs index e2ae259b..45733fd0 100644 --- a/src/library/raw.rs +++ b/src/library/raw.rs @@ -31,7 +31,7 @@ impl RawNode { /// The language to syntax-highlight in. pub const LANG: Option<EcoString> = None; - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { Ok(Template::show(Self { text: args.expect("text")?, block: args.named("block")?.unwrap_or(false), diff --git a/src/library/shape.rs b/src/library/shape.rs index dd306f91..acb011ea 100644 --- a/src/library/shape.rs +++ b/src/library/shape.rs @@ -20,7 +20,7 @@ impl<const S: ShapeKind> ShapeNode<S> { /// How much to pad the shape's content. pub const PADDING: Linear = Linear::zero(); - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { let size = match S { SQUARE => args.named::<Length>("size")?.map(Linear::from), CIRCLE => args.named::<Length>("radius")?.map(|r| 2.0 * Linear::from(r)), @@ -46,7 +46,7 @@ impl<const S: ShapeKind> ShapeNode<S> { impl<const S: ShapeKind> Layout for ShapeNode<S> { fn layout( &self, - ctx: &mut LayoutContext, + vm: &mut Vm, regions: &Regions, styles: StyleChain, ) -> Vec<Constrained<Arc<Frame>>> { @@ -61,7 +61,7 @@ impl<const S: ShapeKind> Layout for ShapeNode<S> { let child = child.clone().padded(Sides::splat(padding)); let mut pod = Regions::one(regions.current, regions.base, regions.expand); - frames = child.layout(ctx, &pod, styles); + frames = child.layout(vm, &pod, styles); // Relayout with full expansion into square region to make sure // the result is really a square or circle. @@ -77,7 +77,7 @@ impl<const S: ShapeKind> Layout for ShapeNode<S> { pod.current = Size::splat(length); pod.expand = Spec::splat(true); - frames = child.layout(ctx, &pod, styles); + frames = child.layout(vm, &pod, styles); frames[0].cts = Constraints::tight(regions); } } else { diff --git a/src/library/spacing.rs b/src/library/spacing.rs index 3e26cb3c..f9676d4c 100644 --- a/src/library/spacing.rs +++ b/src/library/spacing.rs @@ -7,7 +7,7 @@ pub struct HNode; #[class] impl HNode { - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { Ok(Template::Horizontal(args.expect("spacing")?)) } } @@ -17,7 +17,7 @@ pub struct VNode; #[class] impl VNode { - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { Ok(Template::Vertical(args.expect("spacing")?)) } } diff --git a/src/library/stack.rs b/src/library/stack.rs index 88605a30..287731b8 100644 --- a/src/library/stack.rs +++ b/src/library/stack.rs @@ -16,7 +16,7 @@ pub struct StackNode { #[class] impl StackNode { - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { Ok(Template::block(Self { dir: args.named("dir")?.unwrap_or(Dir::TTB), spacing: args.named("spacing")?, @@ -28,7 +28,7 @@ impl StackNode { impl Layout for StackNode { fn layout( &self, - ctx: &mut LayoutContext, + vm: &mut Vm, regions: &Regions, styles: StyleChain, ) -> Vec<Constrained<Arc<Frame>>> { @@ -48,7 +48,7 @@ impl Layout for StackNode { layouter.layout_spacing(kind); } - layouter.layout_node(ctx, node, styles); + layouter.layout_node(vm, node, styles); deferred = self.spacing; } } @@ -163,12 +163,7 @@ impl StackLayouter { } /// Layout an arbitrary node. - pub fn layout_node( - &mut self, - ctx: &mut LayoutContext, - node: &LayoutNode, - styles: StyleChain, - ) { + pub fn layout_node(&mut self, vm: &mut Vm, node: &LayoutNode, styles: StyleChain) { if self.regions.is_full() { self.finish_region(); } @@ -179,7 +174,7 @@ impl StackLayouter { .and_then(|node| node.aligns.get(self.axis)) .unwrap_or(self.dir.start().into()); - let frames = node.layout(ctx, &self.regions, styles); + let frames = node.layout(vm, &self.regions, styles); let len = frames.len(); for (i, frame) in frames.into_iter().enumerate() { // Grow our size, shrink the region and save the frame for later. diff --git a/src/library/table.rs b/src/library/table.rs index 3f30dd9e..dfefa21d 100644 --- a/src/library/table.rs +++ b/src/library/table.rs @@ -27,7 +27,7 @@ impl TableNode { /// How much to pad the cells's content. pub const PADDING: Linear = Length::pt(5.0).into(); - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { let columns = args.named("columns")?.unwrap_or_default(); let rows = args.named("rows")?.unwrap_or_default(); let base_gutter: Vec<TrackSizing> = args.named("gutter")?.unwrap_or_default(); diff --git a/src/library/text.rs b/src/library/text.rs index 4ee64e7a..9fbc8605 100644 --- a/src/library/text.rs +++ b/src/library/text.rs @@ -103,7 +103,7 @@ impl TextNode { #[skip] pub const LINK: Option<EcoString> = None; - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { // The text constructor is special: It doesn't create a text node. // Instead, it leaves the passed argument structurally unchanged, but // styles all text in it. @@ -117,7 +117,7 @@ pub struct StrongNode(pub Template); #[class] impl StrongNode { - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { Ok(Template::show(Self(args.expect("body")?))) } } @@ -134,7 +134,7 @@ pub struct EmphNode(pub Template); #[class] impl EmphNode { - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { Ok(Template::show(Self(args.expect("body")?))) } } diff --git a/src/library/transform.rs b/src/library/transform.rs index cc40921b..91d4b574 100644 --- a/src/library/transform.rs +++ b/src/library/transform.rs @@ -17,7 +17,7 @@ impl<const T: TransformKind> TransformNode<T> { /// The origin of the transformation. pub const ORIGIN: Spec<Option<Align>> = Spec::default(); - fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> { + fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Template> { let transform = match T { MOVE => { let tx = args.named("x")?.unwrap_or_default(); @@ -46,12 +46,12 @@ impl<const T: TransformKind> TransformNode<T> { impl<const T: TransformKind> Layout for TransformNode<T> { fn layout( &self, - ctx: &mut LayoutContext, + vm: &mut Vm, regions: &Regions, styles: StyleChain, ) -> Vec<Constrained<Arc<Frame>>> { let origin = styles.get(Self::ORIGIN).unwrap_or(Align::CENTER_HORIZON); - let mut frames = self.child.layout(ctx, regions, styles); + let mut frames = self.child.layout(vm, regions, styles); for Constrained { item: frame, .. } in &mut frames { let Spec { x, y } = origin.zip(frame.size).map(|(o, s)| o.resolve(s)); diff --git a/src/library/utility.rs b/src/library/utility.rs index 3b9b8b04..91f0e3ad 100644 --- a/src/library/utility.rs +++ b/src/library/utility.rs @@ -7,7 +7,7 @@ use super::prelude::*; use crate::eval::Array; /// Ensure that a condition is fulfilled. -pub fn assert(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn assert(_: &mut Vm, args: &mut Args) -> TypResult<Value> { let Spanned { v, span } = args.expect::<Spanned<bool>>("condition")?; if !v { bail!(span, "assertion failed"); @@ -16,17 +16,17 @@ pub fn assert(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { } /// The name of a value's type. -pub fn type_(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn type_(_: &mut Vm, args: &mut Args) -> TypResult<Value> { Ok(args.expect::<Value>("value")?.type_name().into()) } /// The string representation of a value. -pub fn repr(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn repr(_: &mut Vm, args: &mut Args) -> TypResult<Value> { Ok(args.expect::<Value>("value")?.repr().into()) } /// Join a sequence of values, optionally interspersing it with another value. -pub fn join(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn join(_: &mut Vm, args: &mut Args) -> TypResult<Value> { let span = args.span; let sep = args.named::<Value>("sep")?.unwrap_or(Value::None); @@ -46,7 +46,7 @@ pub fn join(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { } /// Convert a value to a integer. -pub fn int(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn int(_: &mut Vm, args: &mut Args) -> TypResult<Value> { let Spanned { v, span } = args.expect("value")?; Ok(Value::Int(match v { Value::Bool(v) => v as i64, @@ -61,7 +61,7 @@ pub fn int(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { } /// Convert a value to a float. -pub fn float(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn float(_: &mut Vm, args: &mut Args) -> TypResult<Value> { let Spanned { v, span } = args.expect("value")?; Ok(Value::Float(match v { Value::Int(v) => v as f64, @@ -75,7 +75,7 @@ pub fn float(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { } /// Try to convert a value to a string. -pub fn str(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn str(_: &mut Vm, args: &mut Args) -> TypResult<Value> { let Spanned { v, span } = args.expect("value")?; Ok(Value::Str(match v { Value::Int(v) => format_eco!("{}", v), @@ -86,7 +86,7 @@ pub fn str(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { } /// Create an RGB(A) color. -pub fn rgb(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn rgb(_: &mut Vm, args: &mut Args) -> TypResult<Value> { Ok(Value::from( if let Some(string) = args.find::<Spanned<EcoString>>()? { match RgbaColor::from_str(&string.v) { @@ -120,7 +120,7 @@ pub fn rgb(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { } /// Create a CMYK color. -pub fn cmyk(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn cmyk(_: &mut Vm, args: &mut Args) -> TypResult<Value> { struct Component(u8); castable! { @@ -141,7 +141,7 @@ pub fn cmyk(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { } /// The absolute value of a numeric value. -pub fn abs(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn abs(_: &mut Vm, args: &mut Args) -> TypResult<Value> { let Spanned { v, span } = args.expect("numeric value")?; Ok(match v { Value::Int(v) => Value::Int(v.abs()), @@ -156,27 +156,27 @@ pub fn abs(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { } /// The minimum of a sequence of values. -pub fn min(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn min(_: &mut Vm, args: &mut Args) -> TypResult<Value> { minmax(args, Ordering::Less) } /// The maximum of a sequence of values. -pub fn max(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn max(_: &mut Vm, args: &mut Args) -> TypResult<Value> { minmax(args, Ordering::Greater) } /// Whether an integer is even. -pub fn even(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn even(_: &mut Vm, args: &mut Args) -> TypResult<Value> { Ok(Value::Bool(args.expect::<i64>("integer")? % 2 == 0)) } /// Whether an integer is odd. -pub fn odd(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn odd(_: &mut Vm, args: &mut Args) -> TypResult<Value> { Ok(Value::Bool(args.expect::<i64>("integer")? % 2 != 0)) } /// The modulo of two numbers. -pub fn modulo(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn modulo(_: &mut Vm, args: &mut Args) -> TypResult<Value> { let Spanned { v: v1, span: span1 } = args.expect("integer or float")?; let Spanned { v: v2, span: span2 } = args.expect("integer or float")?; @@ -227,7 +227,7 @@ fn minmax(args: &mut Args, goal: Ordering) -> TypResult<Value> { } /// Create a sequence of numbers. -pub fn range(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn range(_: &mut Vm, args: &mut Args) -> TypResult<Value> { let first = args.expect::<i64>("end")?; let (start, end) = match args.eat::<i64>()? { Some(second) => (first, second), @@ -252,19 +252,19 @@ pub fn range(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { } /// Convert a string to lowercase. -pub fn lower(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn lower(_: &mut Vm, args: &mut Args) -> TypResult<Value> { Ok(args.expect::<EcoString>("string")?.to_lowercase().into()) } /// Convert a string to uppercase. -pub fn upper(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn upper(_: &mut Vm, args: &mut Args) -> TypResult<Value> { Ok(args.expect::<EcoString>("string")?.to_uppercase().into()) } /// Converts an integer into a roman numeral. /// /// Works for integer between 0 and 3,999,999. -pub fn roman(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn roman(_: &mut Vm, args: &mut Args) -> TypResult<Value> { // Adapted from Yann Villessuzanne's roman.rs under the Unlicense, at // https://github.com/linfir/roman.rs/ static PAIRS: &'static [(&'static str, usize)] = &[ @@ -314,7 +314,7 @@ pub fn roman(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { } /// Convert a number into a roman numeral. -pub fn symbol(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn symbol(_: &mut Vm, args: &mut Args) -> TypResult<Value> { static SYMBOLS: &'static [char] = &['*', '†', '‡', '§', '‖', '¶']; let n = args.expect::<usize>("non-negative integer")?; @@ -327,7 +327,7 @@ pub fn symbol(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { } /// The length of a string, an array or a dictionary. -pub fn len(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn len(_: &mut Vm, args: &mut Args) -> TypResult<Value> { let Spanned { v, span } = args.expect("collection")?; Ok(Value::Int(match v { Value::Str(v) => v.len() as i64, @@ -342,7 +342,7 @@ pub fn len(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { } /// The sorted version of an array. -pub fn sorted(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn sorted(_: &mut Vm, args: &mut Args) -> TypResult<Value> { let Spanned { v, span } = args.expect::<Spanned<Array>>("array")?; Ok(Value::Array(v.sorted().at(span)?)) } |
