summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2020-10-04 23:31:35 +0200
committerLaurenz <laurmaedje@gmail.com>2020-10-04 23:31:35 +0200
commit335fa2d118718b4dba539294a8ef6c96c5bbf09e (patch)
tree08e48d0c18c350bc9479d0d801d2320628d8e4a2 /src
parent605ab104c5e041c345007020d277b4c6267debe6 (diff)
Small improvements 🍪
Diffstat (limited to 'src')
-rw-r--r--src/eval/args.rs39
-rw-r--r--src/eval/convert.rs11
-rw-r--r--src/eval/state.rs2
-rw-r--r--src/eval/value.rs28
-rw-r--r--src/export/pdf.rs6
-rw-r--r--src/layout/line.rs44
-rw-r--r--src/layout/mod.rs29
-rw-r--r--src/layout/stack.rs73
-rw-r--r--src/layout/tree.rs4
-rw-r--r--src/lib.rs29
-rw-r--r--src/library/align.rs3
-rw-r--r--src/library/boxed.rs2
-rw-r--r--src/library/color.rs8
-rw-r--r--src/library/font.rs2
-rw-r--r--src/library/mod.rs1
-rw-r--r--src/library/page.rs2
-rw-r--r--src/library/spacing.rs4
-rw-r--r--src/paper.rs2
-rw-r--r--src/parse/tests.rs1
-rw-r--r--src/syntax/ast/expr.rs3
-rw-r--r--src/syntax/ast/mod.rs2
21 files changed, 166 insertions, 129 deletions
diff --git a/src/eval/args.rs b/src/eval/args.rs
index d71cc374..b89ee61f 100644
--- a/src/eval/args.rs
+++ b/src/eval/args.rs
@@ -2,7 +2,9 @@
use std::mem;
-use super::*;
+use super::{Convert, RefKey, ValueDict};
+use crate::layout::LayoutContext;
+use crate::syntax::{SpanWith, Spanned};
/// A wrapper around a dictionary value that simplifies argument parsing in
/// functions.
@@ -21,14 +23,44 @@ impl Args {
{
self.0.v.remove(key).and_then(|entry| {
let span = entry.value.span;
- let (t, diag) = T::convert(entry.value);
+ let (result, diag) = T::convert(entry.value);
if let Some(diag) = diag {
ctx.f.diags.push(diag.span_with(span))
}
- t.ok()
+ result.ok()
})
}
+ /// This is the same as [`get`], except that it generates an error about a
+ /// missing argument with the given `name` if the key does not exist.
+ ///
+ /// [`get`]: #method.get
+ pub fn need<'a, K, T>(
+ &mut self,
+ ctx: &mut LayoutContext,
+ key: K,
+ name: &str,
+ ) -> Option<T>
+ where
+ K: Into<RefKey<'a>>,
+ T: Convert,
+ {
+ match self.0.v.remove(key) {
+ Some(entry) => {
+ let span = entry.value.span;
+ let (result, diag) = T::convert(entry.value);
+ if let Some(diag) = diag {
+ ctx.f.diags.push(diag.span_with(span))
+ }
+ result.ok()
+ }
+ None => {
+ ctx.f.diags.push(error!(self.0.span, "missing argument: {}", name));
+ None
+ }
+ }
+ }
+
/// Retrieve and remove the first matching positional argument.
pub fn find<T>(&mut self) -> Option<T>
where
@@ -104,6 +136,7 @@ impl Args {
#[cfg(test)]
mod tests {
+ use super::super::{Dict, SpannedEntry, Value};
use super::*;
fn entry(value: Value) -> SpannedEntry<Value> {
diff --git a/src/eval/convert.rs b/src/eval/convert.rs
index a32d5912..4c177c5b 100644
--- a/src/eval/convert.rs
+++ b/src/eval/convert.rs
@@ -4,11 +4,12 @@ use std::ops::Deref;
use fontdock::{FontStretch, FontStyle, FontWeight};
-use super::*;
+use super::{Value, ValueDict, ValueFunc};
use crate::diag::Diag;
use crate::geom::Linear;
use crate::layout::{Dir, SpecAlign};
use crate::paper::Paper;
+use crate::syntax::{Ident, SpanWith, Spanned, SynTree};
/// Types that values can be converted into.
pub trait Convert: Sized {
@@ -96,9 +97,9 @@ macro_rules! impl_match {
}
impl_match!(Value, "value", v => v);
-impl_match!(Ident, "ident", Value::Ident(v) => v);
+impl_match!(Ident, "identifier", Value::Ident(v) => v);
impl_match!(bool, "bool", Value::Bool(v) => v);
-impl_match!(i64, "int", Value::Int(v) => v);
+impl_match!(i64, "integer", Value::Int(v) => v);
impl_match!(f64, "float",
Value::Int(v) => v as f64,
Value::Float(v) => v,
@@ -112,9 +113,9 @@ impl_match!(Linear, "linear",
);
impl_match!(String, "string", Value::Str(v) => v);
impl_match!(SynTree, "tree", Value::Content(v) => v);
-impl_match!(ValueDict, "dict", Value::Dict(v) => v);
+impl_match!(ValueDict, "dictionary", Value::Dict(v) => v);
impl_match!(ValueFunc, "function", Value::Func(v) => v);
-impl_match!(StringLike, "ident or string",
+impl_match!(StringLike, "identifier or string",
Value::Ident(Ident(v)) => StringLike(v),
Value::Str(v) => StringLike(v),
);
diff --git a/src/eval/state.rs b/src/eval/state.rs
index e4e9f793..3a9f05a4 100644
--- a/src/eval/state.rs
+++ b/src/eval/state.rs
@@ -1,4 +1,4 @@
-//! State.
+//! Evaluation state.
use fontdock::{fallback, FallbackTree, FontStretch, FontStyle, FontVariant, FontWeight};
diff --git a/src/eval/value.rs b/src/eval/value.rs
index 2d83c8d0..85cb261c 100644
--- a/src/eval/value.rs
+++ b/src/eval/value.rs
@@ -1,4 +1,4 @@
-//! Computational values: Syntactical expressions can be evaluated into these.
+//! Computational values.
use std::fmt::{self, Debug, Formatter};
use std::ops::Deref;
@@ -57,9 +57,9 @@ impl Value {
pub fn ty(&self) -> &'static str {
match self {
Self::None => "none",
- Self::Ident(_) => "ident",
+ Self::Ident(_) => "identifier",
Self::Bool(_) => "bool",
- Self::Int(_) => "int",
+ Self::Int(_) => "integer",
Self::Float(_) => "float",
Self::Relative(_) => "relative",
Self::Length(_) => "length",
@@ -88,6 +88,9 @@ impl Spanned<Value> {
/// the value is represented as layoutable content in a reasonable way.
pub fn into_commands(self) -> Vec<Command> {
match self.v {
+ // Don't print out none values.
+ Value::None => vec![],
+
// Pass-through.
Value::Commands(commands) => commands,
Value::Content(tree) => vec![Command::LayoutSyntaxTree(tree)],
@@ -109,9 +112,6 @@ impl Spanned<Value> {
commands
}
- // Don't print out none values.
- Value::None => vec![],
-
// Format with debug.
val => {
let fmt = format!("{:?}", val);
@@ -144,6 +144,14 @@ impl Debug for Value {
}
}
+/// A dictionary of values.
+///
+/// # Example
+/// ```typst
+/// (false, 12cm, greeting="hi")
+/// ```
+pub type ValueDict = Dict<SpannedEntry<Value>>;
+
/// An wrapper around a reference-counted executable function value.
///
/// The dynamic function object is wrapped in an `Rc` to keep [`Value`]
@@ -192,11 +200,3 @@ impl Debug for ValueFunc {
f.pad("<function>")
}
}
-
-/// A dictionary of values.
-///
-/// # Example
-/// ```typst
-/// (false, 12cm, greeting="hi")
-/// ```
-pub type ValueDict = Dict<SpannedEntry<Value>>;
diff --git a/src/export/pdf.rs b/src/export/pdf.rs
index fb1b3e3b..ccbc01f1 100644
--- a/src/export/pdf.rs
+++ b/src/export/pdf.rs
@@ -26,11 +26,11 @@ use crate::length::Length;
/// The raw _PDF_ is written into the `target` writable, returning the number of
/// bytes written.
pub fn export<W: Write>(
- layout: &[BoxLayout],
+ layouts: &[BoxLayout],
loader: &FontLoader,
target: W,
) -> io::Result<usize> {
- PdfExporter::new(layout, loader, target)?.write()
+ PdfExporter::new(layouts, loader, target)?.write()
}
struct PdfExporter<'a, W: Write> {
@@ -42,7 +42,7 @@ struct PdfExporter<'a, W: Write> {
/// tree and so on. These offsets are computed in the beginning and stored
/// here.
offsets: Offsets,
- // Font remapping, see below at `remap_fonts`.
+ // Font remapping, for more information see `remap_fonts`.
to_pdf: HashMap<FaceId, usize>,
to_layout: Vec<FaceId>,
}
diff --git a/src/layout/line.rs b/src/layout/line.rs
index 9de8348c..baef9fb0 100644
--- a/src/layout/line.rs
+++ b/src/layout/line.rs
@@ -12,7 +12,9 @@ use super::*;
/// Performs the line layouting.
pub struct LineLayouter {
+ /// The context used for line layouting.
ctx: LineContext,
+ /// The underlying layouter that stacks the finished lines.
stack: StackLayouter,
/// The in-progress line.
run: LineRun,
@@ -36,27 +38,6 @@ pub struct LineContext {
pub line_spacing: f64,
}
-/// A sequence of boxes with the same alignment. A real line can consist of
-/// multiple runs with different alignments.
-struct LineRun {
- /// The so-far accumulated items of the run.
- layouts: Vec<(f64, BoxLayout)>,
- /// The summed width and maximal height of the run.
- size: Size,
- /// The alignment of all layouts in the line.
- ///
- /// When a new run is created the alignment is yet to be determined and
- /// `None` as such. Once a layout is added, its alignment decides the
- /// alignment for the whole run.
- align: Option<LayoutAlign>,
- /// The amount of space left by another run on the same line or `None` if
- /// this is the only run so far.
- usable: Option<f64>,
- /// The spacing state. This influences how new spacing is handled, e.g. hard
- /// spacing may override soft spacing.
- last_spacing: LastSpacing,
-}
-
impl LineLayouter {
/// Create a new line layouter.
pub fn new(ctx: LineContext) -> Self {
@@ -259,6 +240,27 @@ impl LineLayouter {
}
}
+/// A sequence of boxes with the same alignment. A real line can consist of
+/// multiple runs with different alignments.
+struct LineRun {
+ /// The so-far accumulated items of the run.
+ layouts: Vec<(f64, BoxLayout)>,
+ /// The summed width and maximal height of the run.
+ size: Size,
+ /// The alignment of all layouts in the line.
+ ///
+ /// When a new run is created the alignment is yet to be determined and
+ /// `None` as such. Once a layout is added, its alignment decides the
+ /// alignment for the whole run.
+ align: Option<LayoutAlign>,
+ /// The amount of space left by another run on the same line or `None` if
+ /// this is the only run so far.
+ usable: Option<f64>,
+ /// The spacing state. This influences how new spacing is handled, e.g. hard
+ /// spacing may override soft spacing.
+ last_spacing: LastSpacing,
+}
+
impl LineRun {
fn new() -> Self {
Self {
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 75d7b96b..52f7e0e6 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -46,7 +46,6 @@ pub async fn layout(
};
let layouts = layout_tree(&tree, &mut ctx).await;
-
Pass::new(layouts, ctx.f)
}
@@ -177,12 +176,11 @@ pub enum Command {
SetTextState(TextState),
/// Update the page style.
SetPageState(PageState),
-
- /// Update the alignment for future boxes added to this layouting process.
- SetAlignment(LayoutAlign),
/// Update the layouting system along which future boxes will be laid
/// out. This ends the current line.
SetSystem(LayoutSystem),
+ /// Update the alignment for future boxes added to this layouting process.
+ SetAlignment(LayoutAlign),
}
/// Defines how spacing interacts with surrounding spacing.
@@ -211,26 +209,3 @@ impl SpacingKind {
/// The standard spacing kind used for word spacing.
pub const WORD: Self = Self::Soft(1);
}
-
-/// The spacing kind of the most recently inserted item in a layouting process.
-///
-/// Since the last inserted item may not be spacing at all, this can be `None`.
-#[derive(Debug, Copy, Clone, PartialEq)]
-enum LastSpacing {
- /// The last item was hard spacing.
- Hard,
- /// The last item was soft spacing with the given width and level.
- Soft(f64, u32),
- /// The last item wasn't spacing.
- None,
-}
-
-impl LastSpacing {
- /// The width of the soft space if this is a soft space or zero otherwise.
- fn soft_or_zero(self) -> f64 {
- match self {
- LastSpacing::Soft(space, _) => space,
- _ => 0.0,
- }
- }
-}
diff --git a/src/layout/stack.rs b/src/layout/stack.rs
index e69dc071..dadc40b9 100644
--- a/src/layout/stack.rs
+++ b/src/layout/stack.rs
@@ -23,7 +23,9 @@ use super::*;
/// Performs the stack layouting.
pub struct StackLayouter {
+ /// The context used for stack layouting.
ctx: StackContext,
+ /// The finished layouts.
layouts: Vec<BoxLayout>,
/// The in-progress space.
space: Space,
@@ -45,30 +47,6 @@ pub struct StackContext {
pub repeat: bool,
}
-/// A layout space composed of subspaces which can have different systems and
-/// alignments.
-struct Space {
- /// The index of this space in `ctx.spaces`.
- index: usize,
- /// Whether to include a layout for this space even if it would be empty.
- hard: bool,
- /// The so-far accumulated layouts.
- layouts: Vec<(LayoutSystem, BoxLayout)>,
- /// The specialized size of this space.
- size: Size,
- /// The specialized remaining space.
- usable: Size,
- /// The specialized extra-needed size to affect the size at all.
- extra: Size,
- /// Dictate which alignments for new boxes are still allowed and which
- /// require a new space to be started. For example, after an `End`-aligned
- /// item, no `Start`-aligned one can follow.
- rulers: Sides<GenAlign>,
- /// The spacing state. This influences how new spacing is handled, e.g. hard
- /// spacing may override soft spacing.
- last_spacing: LastSpacing,
-}
-
impl StackLayouter {
/// Create a new stack layouter.
pub fn new(ctx: StackContext) -> Self {
@@ -387,6 +365,30 @@ impl StackLayouter {
}
}
+/// A layout space composed of subspaces which can have different systems and
+/// alignments.
+struct Space {
+ /// The index of this space in `ctx.spaces`.
+ index: usize,
+ /// Whether to include a layout for this space even if it would be empty.
+ hard: bool,
+ /// The so-far accumulated layouts.
+ layouts: Vec<(LayoutSystem, BoxLayout)>,
+ /// The specialized size of this space.
+ size: Size,
+ /// The specialized remaining space.
+ usable: Size,
+ /// The specialized extra-needed size to affect the size at all.
+ extra: Size,
+ /// Dictate which alignments for new boxes are still allowed and which
+ /// require a new space to be started. For example, after an `End`-aligned
+ /// item, no `Start`-aligned one can follow.
+ rulers: Sides<GenAlign>,
+ /// The spacing state. This influences how new spacing is handled, e.g. hard
+ /// spacing may override soft spacing.
+ last_spacing: LastSpacing,
+}
+
impl Space {
fn new(index: usize, hard: bool, usable: Size) -> Self {
Self {
@@ -401,3 +403,26 @@ impl Space {
}
}
}
+
+/// The spacing kind of the most recently inserted item in a layouting process.
+///
+/// Since the last inserted item may not be spacing at all, this can be `None`.
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub(crate) enum LastSpacing {
+ /// The last item was hard spacing.
+ Hard,
+ /// The last item was soft spacing with the given width and level.
+ Soft(f64, u32),
+ /// The last item wasn't spacing.
+ None,
+}
+
+impl LastSpacing {
+ /// The width of the soft space if this is a soft space or zero otherwise.
+ fn soft_or_zero(self) -> f64 {
+ match self {
+ LastSpacing::Soft(space, _) => space,
+ _ => 0.0,
+ }
+ }
+}
diff --git a/src/layout/tree.rs b/src/layout/tree.rs
index 5468a7cd..4e15fb12 100644
--- a/src/layout/tree.rs
+++ b/src/layout/tree.rs
@@ -3,9 +3,7 @@
use super::*;
use crate::eval::Eval;
use crate::shaping;
-use crate::syntax::{
- Deco, Expr, NodeHeading, NodeRaw, Span, SpanWith, Spanned, SynNode, SynTree,
-};
+use crate::syntax::*;
use crate::DynFuture;
/// Layout a syntax tree in a given context.
diff --git a/src/lib.rs b/src/lib.rs
index d2bd076d..ef81a8ae 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,24 +2,25 @@
//!
//! # Steps
//! - **Parsing:** The parsing step first transforms a plain string into an
-//! [iterator of tokens][tokens]. Then, a [parser] constructs a syntax tree
-//! from the token stream. The structures describing the tree can be found in
-//! the [syntax] module.
+//! [iterator of tokens][tokens]. This token stream is [parsed] into a [syntax
+//! tree]. The structures describing the tree can be found in the [ast]
+//! module.
//! - **Layouting:** The next step is to transform the syntax tree into a
-//! portable representation of the typesetted document. Types for these can be
-//! found in the [layout] module. A finished layout ready for exporting is a
-//! [`MultiLayout`] consisting of multiple boxes (or pages).
+//! portable representation of the typesetted document. The final output
+//! consists of a vector of [`BoxLayouts`] (corresponding to pages), ready for
+//! exporting.
//! - **Exporting:** The finished layout can then be exported into a supported
//! format. Submodules for these formats are located in the [export] module.
//! Currently, the only supported output format is [_PDF_].
//!
-//! [tokens]: parse/struct.Tokens.html
-//! [parser]: parse/fn.parse.html
-//! [syntax]: syntax/index.html
+//! [tokens]: parsing/struct.Tokens.html
+//! [parsed]: parsing/fn.parse.html
+//! [syntax tree]: syntax/ast/type.SynTree.html
+//! [ast]: syntax/ast/index.html
//! [layout]: layout/index.html
+//! [`BoxLayouts`]: layout/struct.BoxLayout.html
//! [export]: export/index.html
//! [_PDF_]: export/pdf/index.html
-//! [`MultiLayout`]: layout/type.MultiLayout.html
#[macro_use]
pub mod diag;
@@ -56,7 +57,7 @@ pub async fn typeset(
) -> Pass<Vec<BoxLayout>> {
let parsed = parse::parse(src);
let layouted = layout::layout(&parsed.output, state, loader).await;
- let feedback = Feedback::merge(parsed.feedback, layouted.feedback);
+ let feedback = Feedback::join(parsed.feedback, layouted.feedback);
Pass::new(layouted.output, feedback)
}
@@ -108,8 +109,8 @@ impl Feedback {
Self { diags: vec![], decos: vec![] }
}
- /// Merged two feedbacks into one.
- pub fn merge(mut a: Self, b: Self) -> Self {
+ /// Merge two feedbacks into one.
+ pub fn join(mut a: Self, b: Self) -> Self {
a.extend(b);
a
}
@@ -120,7 +121,7 @@ impl Feedback {
self.decos.extend(more.decos);
}
- /// Add more feedback whose spans are local and need to be offset by an
+ /// Add more feedback whose spans are local and need to be translated by an
/// `offset` to be correct in this feedback's context.
pub fn extend_offset(&mut self, more: Self, offset: Pos) {
self.diags.extend(more.diags.offset(offset));
diff --git a/src/library/align.rs b/src/library/align.rs
index 674ecceb..eaef4d87 100644
--- a/src/library/align.rs
+++ b/src/library/align.rs
@@ -1,4 +1,4 @@
-use super::*;
+use crate::prelude::*;
/// `align`: Align content along the layouting axes.
///
@@ -16,7 +16,6 @@ use super::*;
/// There may not be two alignment specifications for the same axis.
pub async fn align(mut args: Args, ctx: &mut LayoutContext) -> Value {
let body = args.find::<SynTree>();
-
let h = args.get::<_, Spanned<SpecAlign>>(ctx, "horizontal");
let v = args.get::<_, Spanned<SpecAlign>>(ctx, "vertical");
let pos = args.find_all::<Spanned<SpecAlign>>();
diff --git a/src/library/boxed.rs b/src/library/boxed.rs
index 81e3a96a..085176e0 100644
--- a/src/library/boxed.rs
+++ b/src/library/boxed.rs
@@ -1,5 +1,5 @@
-use super::*;
use crate::geom::Linear;
+use crate::prelude::*;
/// `box`: Layouts its contents into a box.
///
diff --git a/src/library/color.rs b/src/library/color.rs
index 143ce70a..a4958c53 100644
--- a/src/library/color.rs
+++ b/src/library/color.rs
@@ -1,11 +1,11 @@
-use super::*;
use crate::color::RgbaColor;
+use crate::prelude::*;
/// `rgb`: Create an RGB(A) color.
pub async fn rgb(mut args: Args, ctx: &mut LayoutContext) -> Value {
- let r = args.get::<_, Spanned<i64>>(ctx, 0);
- let g = args.get::<_, Spanned<i64>>(ctx, 1);
- let b = args.get::<_, Spanned<i64>>(ctx, 2);
+ let r = args.need::<_, Spanned<i64>>(ctx, 0, "red value");
+ let g = args.need::<_, Spanned<i64>>(ctx, 1, "green value");
+ let b = args.need::<_, Spanned<i64>>(ctx, 2, "blue value");
let a = args.get::<_, Spanned<i64>>(ctx, 3);
args.done(ctx);
diff --git a/src/library/font.rs b/src/library/font.rs
index 0a28beaa..60380def 100644
--- a/src/library/font.rs
+++ b/src/library/font.rs
@@ -1,8 +1,8 @@
use fontdock::{FontStretch, FontStyle, FontWeight};
-use super::*;
use crate::eval::StringLike;
use crate::geom::Linear;
+use crate::prelude::*;
/// `font`: Configure the font.
///
diff --git a/src/library/mod.rs b/src/library/mod.rs
index 66fc5d59..191a3920 100644
--- a/src/library/mod.rs
+++ b/src/library/mod.rs
@@ -15,7 +15,6 @@ pub use page::*;
pub use spacing::*;
use crate::eval::{Scope, ValueFunc};
-use crate::prelude::*;
macro_rules! std {
($($name:literal => $func:expr),* $(,)?) => {
diff --git a/src/library/page.rs b/src/library/page.rs
index db76d2a1..2bf9f019 100644
--- a/src/library/page.rs
+++ b/src/library/page.rs
@@ -1,9 +1,9 @@
use std::mem;
-use super::*;
use crate::eval::Absolute;
use crate::geom::{Linear, Sides};
use crate::paper::{Paper, PaperClass};
+use crate::prelude::*;
/// `page`: Configure pages.
///
diff --git a/src/library/spacing.rs b/src/library/spacing.rs
index b97f4640..b38f0607 100644
--- a/src/library/spacing.rs
+++ b/src/library/spacing.rs
@@ -1,6 +1,6 @@
-use super::*;
use crate::geom::Linear;
use crate::layout::SpacingKind;
+use crate::prelude::*;
/// `h`: Add horizontal spacing.
///
@@ -19,7 +19,7 @@ pub async fn v(args: Args, ctx: &mut LayoutContext) -> Value {
}
fn spacing(mut args: Args, ctx: &mut LayoutContext, axis: SpecAxis) -> Value {
- let spacing = args.get::<_, Linear>(ctx, 0);
+ let spacing = args.need::<_, Linear>(ctx, 0, "spacing");
args.done(ctx);
Value::Commands(if let Some(spacing) = spacing {
diff --git a/src/paper.rs b/src/paper.rs
index 30e5d8e7..aff4cdd7 100644
--- a/src/paper.rs
+++ b/src/paper.rs
@@ -37,7 +37,7 @@ pub enum PaperClass {
}
impl PaperClass {
- /// The default margin ratios for this page class.
+ /// The default margins for this page class.
pub fn default_margins(self) -> Sides<Linear> {
let f = Linear::rel;
let s = |l, r, t, b| Sides::new(f(l), f(r), f(t), f(b));
diff --git a/src/parse/tests.rs b/src/parse/tests.rs
index 108b4b29..644b7f16 100644
--- a/src/parse/tests.rs
+++ b/src/parse/tests.rs
@@ -89,6 +89,7 @@ macro_rules! Call {
}};
($($tts:tt)*) => { Expr::Call(Call![@$($tts)*]) };
}
+
fn Unary(op: impl Into<Spanned<UnOp>>, expr: impl Into<Spanned<Expr>>) -> Expr {
Expr::Unary(ExprUnary {
op: op.into(),
diff --git a/src/syntax/ast/expr.rs b/src/syntax/ast/expr.rs
index 433dcca2..09729f52 100644
--- a/src/syntax/ast/expr.rs
+++ b/src/syntax/ast/expr.rs
@@ -21,6 +21,9 @@ pub struct ExprCall {
/// The name of the function.
pub name: Spanned<Ident>,
/// The arguments to the function.
+ ///
+ /// In case of a bracketed invocation with a body, the body is _not_
+ /// included in the span for the sake of clearer error messages.
pub args: Spanned<LitDict>,
}
diff --git a/src/syntax/ast/mod.rs b/src/syntax/ast/mod.rs
index df0fbc23..0d394e54 100644
--- a/src/syntax/ast/mod.rs
+++ b/src/syntax/ast/mod.rs
@@ -8,4 +8,4 @@ pub use expr::*;
pub use lit::*;
pub use tree::*;
-use super::*;
+use super::{Ident, SpanVec, Spanned};