diff --git a/src/eval/mod.rs b/src/eval/mod.rs index 4e7a0e843..9e6fad8fd 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -177,6 +177,33 @@ impl Eval for Expr { type Output = Value; fn eval(&self, ctx: &mut EvalContext) -> TypResult { + match self { + Self::Ident(v) => v.eval(ctx), + Self::Lit(v) => v.eval(ctx), + Self::Array(v) => v.eval(ctx).map(Value::Array), + Self::Dict(v) => v.eval(ctx).map(Value::Dict), + Self::Template(v) => v.eval(ctx).map(Value::Template), + Self::Group(v) => v.eval(ctx), + Self::Block(v) => v.eval(ctx), + Self::Call(v) => v.eval(ctx), + Self::Closure(v) => v.eval(ctx), + Self::With(v) => v.eval(ctx), + Self::Unary(v) => v.eval(ctx), + Self::Binary(v) => v.eval(ctx), + Self::Let(v) => v.eval(ctx), + Self::If(v) => v.eval(ctx), + Self::While(v) => v.eval(ctx), + Self::For(v) => v.eval(ctx), + Self::Import(v) => v.eval(ctx), + Self::Include(v) => v.eval(ctx), + } + } +} + +impl Eval for Lit { + type Output = Value; + + fn eval(&self, _: &mut EvalContext) -> TypResult { Ok(match *self { Self::None(_) => Value::None, Self::Auto(_) => Value::Auto, @@ -188,23 +215,6 @@ impl Eval for Expr { Self::Percent(_, v) => Value::Relative(Relative::new(v / 100.0)), Self::Fractional(_, v) => Value::Fractional(Fractional::new(v)), Self::Str(_, ref v) => Value::Str(v.clone()), - Self::Ident(ref v) => v.eval(ctx)?, - Self::Array(ref v) => Value::Array(v.eval(ctx)?), - Self::Dict(ref v) => Value::Dict(v.eval(ctx)?), - Self::Template(ref v) => Value::Template(v.eval(ctx)?), - Self::Group(ref v) => v.eval(ctx)?, - Self::Block(ref v) => v.eval(ctx)?, - Self::Call(ref v) => v.eval(ctx)?, - Self::Closure(ref v) => v.eval(ctx)?, - Self::With(ref v) => v.eval(ctx)?, - Self::Unary(ref v) => v.eval(ctx)?, - Self::Binary(ref v) => v.eval(ctx)?, - Self::Let(ref v) => v.eval(ctx)?, - Self::If(ref v) => v.eval(ctx)?, - Self::While(ref v) => v.eval(ctx)?, - Self::For(ref v) => v.eval(ctx)?, - Self::Import(ref v) => v.eval(ctx)?, - Self::Include(ref v) => v.eval(ctx)?, }) } } @@ -674,8 +684,8 @@ impl Walk for SyntaxTree { impl Walk for SyntaxNode { fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> { match self { - Self::Text(_) => {} Self::Space => {} + Self::Text(_) => {} Self::Linebreak(_) => {} Self::Parbreak(_) => {} Self::Strong(_) => {} diff --git a/src/exec/mod.rs b/src/exec/mod.rs index 762b555d0..373a32637 100644 --- a/src/exec/mod.rs +++ b/src/exec/mod.rs @@ -52,8 +52,8 @@ impl ExecWithMap for SyntaxTree { impl ExecWithMap for SyntaxNode { fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) { match self { - Self::Text(text) => ctx.push_text(text), Self::Space => ctx.push_word_space(), + Self::Text(text) => ctx.push_text(text), Self::Linebreak(_) => ctx.linebreak(), Self::Parbreak(_) => ctx.parbreak(), Self::Strong(_) => ctx.state.font_mut().strong ^= true, diff --git a/src/geom/relative.rs b/src/geom/relative.rs index 6505abff2..149c0b9c9 100644 --- a/src/geom/relative.rs +++ b/src/geom/relative.rs @@ -5,7 +5,7 @@ use super::*; /// A relative length. /// /// _Note_: `50%` is represented as `0.5` here, but stored as `50.0` in the -/// corresponding [literal](crate::syntax::Expr::Percent). +/// corresponding [literal](crate::syntax::Lit::Percent). #[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Relative(N64); diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 2e05dd9e7..c29b9c1c7 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -65,10 +65,12 @@ where if call.wide { let start = p.next_start(); let tree = tree_while(p, true, f); - call.args.items.push(CallArg::Pos(Expr::Template(TemplateExpr { - span: p.span_from(start), - tree: Rc::new(tree), - }))); + call.args.items.push(CallArg::Pos(Expr::Template(Box::new( + TemplateExpr { + span: p.span_from(start), + tree: Rc::new(tree), + }, + )))); } } @@ -181,7 +183,7 @@ fn raw(p: &mut Parser, token: RawToken) -> SyntaxNode { if !token.terminated { p.error(span.end, "expected backtick(s)"); } - SyntaxNode::Raw(raw) + SyntaxNode::Raw(Box::new(raw)) } /// Parse a heading. @@ -201,7 +203,11 @@ fn heading(p: &mut Parser) -> SyntaxNode { } let body = tree_indented(p, column); - SyntaxNode::Heading(HeadingNode { span: p.span_from(start), level, body }) + SyntaxNode::Heading(Box::new(HeadingNode { + span: p.span_from(start), + level, + body, + })) } /// Parse a single list item. @@ -210,7 +216,7 @@ fn list_item(p: &mut Parser) -> SyntaxNode { let column = p.column(start); p.eat_assert(Token::Hyph); let body = tree_indented(p, column); - SyntaxNode::List(ListItem { span: p.span_from(start), body }) + SyntaxNode::List(Box::new(ListItem { span: p.span_from(start), body })) } /// Parse a single enum item. @@ -219,7 +225,11 @@ fn enum_item(p: &mut Parser, number: Option) -> SyntaxNode { let column = p.column(start); p.eat_assert(Token::Numbering(number)); let body = tree_indented(p, column); - SyntaxNode::Enum(EnumItem { span: p.span_from(start), number, body }) + SyntaxNode::Enum(Box::new(EnumItem { + span: p.span_from(start), + number, + body, + })) } /// Parse an expression. @@ -239,8 +249,8 @@ fn expr_with(p: &mut Parser, atomic: bool, min_prec: usize) -> Option { let mut lhs = match p.eat_map(UnOp::from_token) { Some(op) => { let prec = op.precedence(); - let expr = Box::new(expr_with(p, atomic, prec)?); - Expr::Unary(UnaryExpr { span: p.span_from(start), op, expr }) + let expr = expr_with(p, atomic, prec)?; + Expr::Unary(Box::new(UnaryExpr { span: p.span_from(start), op, expr })) } None => primary(p, atomic)?, }; @@ -281,12 +291,12 @@ fn expr_with(p: &mut Parser, atomic: bool, min_prec: usize) -> Option { } let rhs = match expr_with(p, atomic, prec) { - Some(rhs) => Box::new(rhs), + Some(rhs) => rhs, None => break, }; let span = lhs.span().join(rhs.span()); - lhs = Expr::Binary(BinaryExpr { span, lhs: Box::new(lhs), op, rhs }); + lhs = Expr::Binary(Box::new(BinaryExpr { span, lhs, op, rhs })); } Some(lhs) @@ -309,14 +319,14 @@ fn primary(p: &mut Parser, atomic: bool) -> Option { // Arrow means this is a closure's lone parameter. Some(if !atomic && p.eat_if(Token::Arrow) { let body = expr(p)?; - Expr::Closure(ClosureExpr { + Expr::Closure(Box::new(ClosureExpr { span: ident.span.join(body.span()), name: None, params: vec![ClosureParam::Pos(ident)], body: Rc::new(body), - }) + })) } else { - Expr::Ident(ident) + Expr::Ident(Box::new(ident)) }) } @@ -344,18 +354,18 @@ fn primary(p: &mut Parser, atomic: bool) -> Option { /// Parse a literal. fn literal(p: &mut Parser) -> Option { let span = p.peek_span(); - let expr = match p.peek()? { + let lit = match p.peek()? { // Basic values. - Token::None => Expr::None(span), - Token::Auto => Expr::Auto(span), - Token::Bool(b) => Expr::Bool(span, b), - Token::Int(i) => Expr::Int(span, i), - Token::Float(f) => Expr::Float(span, f), - Token::Length(val, unit) => Expr::Length(span, val, unit), - Token::Angle(val, unit) => Expr::Angle(span, val, unit), - Token::Percent(p) => Expr::Percent(span, p), - Token::Fraction(p) => Expr::Fractional(span, p), - Token::Str(token) => Expr::Str(span, { + Token::None => Lit::None(span), + Token::Auto => Lit::Auto(span), + Token::Bool(b) => Lit::Bool(span, b), + Token::Int(i) => Lit::Int(span, i), + Token::Float(f) => Lit::Float(span, f), + Token::Length(val, unit) => Lit::Length(span, val, unit), + Token::Angle(val, unit) => Lit::Angle(span, val, unit), + Token::Percent(p) => Lit::Percent(span, p), + Token::Fraction(p) => Lit::Fractional(span, p), + Token::Str(token) => Lit::Str(span, { if !token.terminated { p.expected_at(span.end, "quote"); } @@ -364,7 +374,7 @@ fn literal(p: &mut Parser) -> Option { _ => return None, }; p.eat(); - Some(expr) + Some(Expr::Lit(Box::new(lit))) } /// Parse something that starts with a parenthesis, which can be either of: @@ -387,21 +397,19 @@ fn parenthesized(p: &mut Parser) -> Option { if p.eat_if(Token::Arrow) { let params = params(p, items); let body = expr(p)?; - return Some(Expr::Closure(ClosureExpr { + return Some(Expr::Closure(Box::new(ClosureExpr { span: span.join(body.span()), name: None, params, body: Rc::new(body), - })); + }))); } // Find out which kind of collection this is. Some(match items.as_slice() { [] => array(p, items, span), [CallArg::Pos(_)] if !has_comma => match items.into_iter().next() { - Some(CallArg::Pos(expr)) => { - Expr::Group(GroupExpr { span, expr: Box::new(expr) }) - } + Some(CallArg::Pos(expr)) => Expr::Group(Box::new(GroupExpr { span, expr })), _ => unreachable!(), }, [CallArg::Pos(_), ..] => array(p, items, span), @@ -454,7 +462,7 @@ fn item(p: &mut Parser) -> Option { let first = expr(p)?; if p.eat_if(Token::Colon) { if let Expr::Ident(name) = first { - Some(CallArg::Named(Named { name, expr: expr(p)? })) + Some(CallArg::Named(Named { name: *name, expr: expr(p)? })) } else { p.error(first.span(), "expected identifier"); expr(p); @@ -479,7 +487,7 @@ fn array(p: &mut Parser, items: Vec, span: Span) -> Expr { None } }); - Expr::Array(ArrayExpr { span, items: iter.collect() }) + Expr::Array(Box::new(ArrayExpr { span, items: iter.collect() })) } /// Convert a collection into a dictionary, producing errors for anything other @@ -496,16 +504,16 @@ fn dict(p: &mut Parser, items: Vec, span: Span) -> Expr { None } }); - Expr::Dict(DictExpr { span, items: iter.collect() }) + Expr::Dict(Box::new(DictExpr { span, items: iter.collect() })) } /// Convert a collection into a list of parameters, producing errors for /// anything other than identifiers, spread operations and named pairs. fn params(p: &mut Parser, items: Vec) -> Vec { let iter = items.into_iter().filter_map(|item| match item { - CallArg::Pos(Expr::Ident(ident)) => Some(ClosureParam::Pos(ident)), + CallArg::Pos(Expr::Ident(ident)) => Some(ClosureParam::Pos(*ident)), CallArg::Named(named) => Some(ClosureParam::Named(named)), - CallArg::Spread(Expr::Ident(ident)) => Some(ClosureParam::Sink(ident)), + CallArg::Spread(Expr::Ident(ident)) => Some(ClosureParam::Sink(*ident)), _ => { p.error(item.span(), "expected identifier"); None @@ -518,7 +526,7 @@ fn params(p: &mut Parser, items: Vec) -> Vec { /// anything other than identifiers. fn idents(p: &mut Parser, items: Vec) -> Vec { let iter = items.into_iter().filter_map(|item| match item { - CallArg::Pos(Expr::Ident(id)) => Some(id), + CallArg::Pos(Expr::Ident(ident)) => Some(*ident), _ => { p.error(item.span(), "expected identifier"); None @@ -532,7 +540,7 @@ fn template(p: &mut Parser) -> Expr { p.start_group(Group::Bracket, TokenMode::Markup); let tree = Rc::new(tree(p)); let span = p.end_group(); - Expr::Template(TemplateExpr { span, tree }) + Expr::Template(Box::new(TemplateExpr { span, tree })) } /// Parse a block expression: `{...}`. @@ -553,7 +561,7 @@ fn block(p: &mut Parser, scoping: bool) -> Expr { p.eat_while(|t| matches!(t, Token::Space(_))); } let span = p.end_group(); - Expr::Block(BlockExpr { span, exprs, scoping }) + Expr::Block(Box::new(BlockExpr { span, exprs, scoping })) } /// Parse a function call. @@ -582,12 +590,12 @@ fn call(p: &mut Parser, callee: Expr) -> Option { args.items.push(CallArg::Pos(body)); } - Some(Expr::Call(CallExpr { + Some(Expr::Call(Box::new(CallExpr { span: p.span_from(callee.span().start), - callee: Box::new(callee), + callee, wide, args, - })) + }))) } /// Parse the arguments to a function call. @@ -601,11 +609,11 @@ fn args(p: &mut Parser) -> CallArgs { /// Parse a with expression. fn with_expr(p: &mut Parser, callee: Expr) -> Option { if p.peek() == Some(Token::LeftParen) { - Some(Expr::With(WithExpr { + Some(Expr::With(Box::new(WithExpr { span: p.span_from(callee.span().start), - callee: Box::new(callee), + callee, args: args(p), - })) + }))) } else { p.expected("argument list"); None @@ -622,7 +630,7 @@ fn let_expr(p: &mut Parser) -> Option { let mut init = None; if p.eat_if(Token::With) { - init = with_expr(p, Expr::Ident(binding.clone())); + init = with_expr(p, Expr::Ident(Box::new(binding.clone()))); } else { // If a parenthesis follows, this is a function definition. let mut maybe_params = None; @@ -643,20 +651,20 @@ fn let_expr(p: &mut Parser) -> Option { // Rewrite into a closure expression if it's a function definition. if let Some(params) = maybe_params { let body = init?; - init = Some(Expr::Closure(ClosureExpr { + init = Some(Expr::Closure(Box::new(ClosureExpr { span: binding.span.join(body.span()), name: Some(binding.clone()), params, body: Rc::new(body), - })); + }))); } } - let_expr = Some(Expr::Let(LetExpr { + let_expr = Some(Expr::Let(Box::new(LetExpr { span: p.span_from(start), binding, - init: init.map(Box::new), - })); + init, + }))); } let_expr @@ -680,12 +688,12 @@ fn if_expr(p: &mut Parser) -> Option { else_body = body(p); } - if_expr = Some(Expr::If(IfExpr { + if_expr = Some(Expr::If(Box::new(IfExpr { span: p.span_from(start), - condition: Box::new(condition), - if_body: Box::new(if_body), - else_body: else_body.map(Box::new), - })); + condition, + if_body, + else_body, + }))); } } @@ -700,11 +708,11 @@ fn while_expr(p: &mut Parser) -> Option { let mut while_expr = None; if let Some(condition) = expr(p) { if let Some(body) = body(p) { - while_expr = Some(Expr::While(WhileExpr { + while_expr = Some(Expr::While(Box::new(WhileExpr { span: p.span_from(start), - condition: Box::new(condition), - body: Box::new(body), - })); + condition, + body, + }))); } } @@ -721,12 +729,12 @@ fn for_expr(p: &mut Parser) -> Option { if p.eat_expect(Token::In) { if let Some(iter) = expr(p) { if let Some(body) = body(p) { - for_expr = Some(Expr::For(ForExpr { + for_expr = Some(Expr::For(Box::new(ForExpr { span: p.span_from(start), pattern, - iter: Box::new(iter), - body: Box::new(body), - })); + iter, + body, + }))); } } } @@ -768,11 +776,11 @@ fn import_expr(p: &mut Parser) -> Option { let mut import_expr = None; if p.eat_expect(Token::From) { if let Some(path) = expr(p) { - import_expr = Some(Expr::Import(ImportExpr { + import_expr = Some(Expr::Import(Box::new(ImportExpr { span: p.span_from(start), imports, - path: Box::new(path), - })); + path, + }))); } } @@ -785,10 +793,7 @@ fn include_expr(p: &mut Parser) -> Option { p.eat_assert(Token::Include); expr(p).map(|path| { - Expr::Include(IncludeExpr { - span: p.span_from(start), - path: Box::new(path), - }) + Expr::Include(Box::new(IncludeExpr { span: p.span_from(start), path })) }) } diff --git a/src/pretty.rs b/src/pretty.rs index 179e5d2dd..573dc6e9c 100644 --- a/src/pretty.rs +++ b/src/pretty.rs @@ -90,8 +90,8 @@ impl Pretty for SyntaxNode { fn pretty(&self, p: &mut Printer) { match self { // TODO: Handle escaping. - Self::Text(text) => p.push_str(text), Self::Space => p.push(' '), + Self::Text(text) => p.push_str(text), Self::Linebreak(_) => p.push_str(r"\"), Self::Parbreak(_) => p.push_str("\n\n"), Self::Strong(_) => p.push('*'), @@ -196,17 +196,8 @@ impl Pretty for EnumItem { impl Pretty for Expr { fn pretty(&self, p: &mut Printer) { match self { - Self::None(_) => p.push_str("none"), - Self::Auto(_) => p.push_str("auto"), - Self::Bool(_, v) => v.pretty(p), - Self::Int(_, v) => v.pretty(p), - Self::Float(_, v) => v.pretty(p), - Self::Length(_, v, u) => write!(p, "{}{}", v, u).unwrap(), - Self::Angle(_, v, u) => write!(p, "{}{}", v, u).unwrap(), - Self::Percent(_, v) => write!(p, "{}%", v).unwrap(), - Self::Fractional(_, v) => write!(p, "{}fr", v).unwrap(), - Self::Str(_, v) => v.pretty(p), Self::Ident(v) => v.pretty(p), + Self::Lit(v) => v.pretty(p), Self::Array(v) => v.pretty(p), Self::Dict(v) => v.pretty(p), Self::Template(v) => v.pretty(p), @@ -227,6 +218,23 @@ impl Pretty for Expr { } } +impl Pretty for Lit { + fn pretty(&self, p: &mut Printer) { + match self { + Self::None(_) => p.push_str("none"), + Self::Auto(_) => p.push_str("auto"), + Self::Bool(_, v) => v.pretty(p), + Self::Int(_, v) => v.pretty(p), + Self::Float(_, v) => v.pretty(p), + Self::Length(_, v, u) => write!(p, "{}{}", v, u).unwrap(), + Self::Angle(_, v, u) => write!(p, "{}{}", v, u).unwrap(), + Self::Percent(_, v) => write!(p, "{}%", v).unwrap(), + Self::Fractional(_, v) => write!(p, "{}fr", v).unwrap(), + Self::Str(_, v) => v.pretty(p), + } + } +} + impl Pretty for ArrayExpr { fn pretty(&self, p: &mut Printer) { p.push('('); diff --git a/src/syntax/expr.rs b/src/syntax/expr.rs index 5b751280e..3a71bedd1 100644 --- a/src/syntax/expr.rs +++ b/src/syntax/expr.rs @@ -6,6 +6,87 @@ use crate::geom::{AngularUnit, LengthUnit}; /// An expression. #[derive(Debug, Clone, PartialEq)] pub enum Expr { + /// An identifier: `left`. + Ident(Box), + /// A literal: `1`, `true`, ... + Lit(Box), + /// An array expression: `(1, "hi", 12cm)`. + Array(Box), + /// A dictionary expression: `(thickness: 3pt, pattern: dashed)`. + Dict(Box), + /// A template expression: `[*Hi* there!]`. + Template(Box), + /// A grouped expression: `(1 + 2)`. + Group(Box), + /// A block expression: `{ let x = 1; x + 2 }`. + Block(Box), + /// A unary operation: `-x`. + Unary(Box), + /// A binary operation: `a + b`. + Binary(Box), + /// An invocation of a function: `f(x, y)`. + Call(Box), + /// A closure expression: `(x, y) => z`. + Closure(Box), + /// A with expression: `f with (x, y: 1)`. + With(Box), + /// A let expression: `let x = 1`. + Let(Box), + /// An if-else expression: `if x { y } else { z }`. + If(Box), + /// A while loop expression: `while x { y }`. + While(Box), + /// A for loop expression: `for x in y { z }`. + For(Box), + /// An import expression: `import a, b, c from "utils.typ"`. + Import(Box), + /// An include expression: `include "chapter1.typ"`. + Include(Box), +} + +impl Expr { + /// The source code location. + pub fn span(&self) -> Span { + match self { + Self::Ident(v) => v.span, + Self::Lit(v) => v.span(), + Self::Array(v) => v.span, + Self::Dict(v) => v.span, + Self::Template(v) => v.span, + Self::Group(v) => v.span, + Self::Block(v) => v.span, + Self::Unary(v) => v.span, + Self::Binary(v) => v.span, + Self::Call(v) => v.span, + Self::Closure(v) => v.span, + Self::With(v) => v.span, + Self::Let(v) => v.span, + Self::If(v) => v.span, + Self::While(v) => v.span, + Self::For(v) => v.span, + Self::Import(v) => v.span, + Self::Include(v) => v.span, + } + } + + /// Whether the expression can be shortened in markup with a hashtag. + pub fn has_short_form(&self) -> bool { + matches!(self, + Self::Ident(_) + | Self::Call(_) + | Self::Let(_) + | Self::If(_) + | Self::While(_) + | Self::For(_) + | Self::Import(_) + | Self::Include(_) + ) + } +} + +/// A literal: `1`, `true`, ... +#[derive(Debug, Clone, PartialEq)] +pub enum Lit { /// The none literal: `none`. None(Span), /// The auto literal: `auto`. @@ -29,43 +110,9 @@ pub enum Expr { Fractional(Span, f64), /// A string literal: `"hello!"`. Str(Span, EcoString), - /// An identifier: `left`. - Ident(Ident), - /// An array expression: `(1, "hi", 12cm)`. - Array(ArrayExpr), - /// A dictionary expression: `(thickness: 3pt, pattern: dashed)`. - Dict(DictExpr), - /// A template expression: `[*Hi* there!]`. - Template(TemplateExpr), - /// A grouped expression: `(1 + 2)`. - Group(GroupExpr), - /// A block expression: `{ let x = 1; x + 2 }`. - Block(BlockExpr), - /// A unary operation: `-x`. - Unary(UnaryExpr), - /// A binary operation: `a + b`. - Binary(BinaryExpr), - /// An invocation of a function: `f(x, y)`. - Call(CallExpr), - /// A closure expression: `(x, y) => z`. - Closure(ClosureExpr), - /// A with expression: `f with (x, y: 1)`. - With(WithExpr), - /// A let expression: `let x = 1`. - Let(LetExpr), - /// An if-else expression: `if x { y } else { z }`. - If(IfExpr), - /// A while loop expression: `while x { y }`. - While(WhileExpr), - /// A for loop expression: `for x in y { z }`. - For(ForExpr), - /// An import expression: `import a, b, c from "utils.typ"`. - Import(ImportExpr), - /// An include expression: `include "chapter1.typ"`. - Include(IncludeExpr), } -impl Expr { +impl Lit { /// The source code location. pub fn span(&self) -> Span { match *self { @@ -79,39 +126,8 @@ impl Expr { Self::Percent(span, _) => span, Self::Fractional(span, _) => span, Self::Str(span, _) => span, - Self::Ident(ref v) => v.span, - Self::Array(ref v) => v.span, - Self::Dict(ref v) => v.span, - Self::Template(ref v) => v.span, - Self::Group(ref v) => v.span, - Self::Block(ref v) => v.span, - Self::Unary(ref v) => v.span, - Self::Binary(ref v) => v.span, - Self::Call(ref v) => v.span, - Self::Closure(ref v) => v.span, - Self::With(ref v) => v.span, - Self::Let(ref v) => v.span, - Self::If(ref v) => v.span, - Self::While(ref v) => v.span, - Self::For(ref v) => v.span, - Self::Import(ref v) => v.span, - Self::Include(ref v) => v.span, } } - - /// Whether the expression can be shortened in markup with a hashtag. - pub fn has_short_form(&self) -> bool { - matches!(self, - Self::Ident(_) - | Self::Call(_) - | Self::Let(_) - | Self::If(_) - | Self::While(_) - | Self::For(_) - | Self::Import(_) - | Self::Include(_) - ) - } } /// An array expression: `(1, "hi", 12cm)`. @@ -163,7 +179,7 @@ pub struct GroupExpr { /// The source code location. pub span: Span, /// The wrapped expression. - pub expr: Box, + pub expr: Expr, } /// A block expression: `{ let x = 1; x + 2 }`. @@ -185,7 +201,7 @@ pub struct UnaryExpr { /// The operator: `-`. pub op: UnOp, /// The expression to operator on: `x`. - pub expr: Box, + pub expr: Expr, } /// A unary operator. @@ -234,11 +250,11 @@ pub struct BinaryExpr { /// The source code location. pub span: Span, /// The left-hand side of the operation: `a`. - pub lhs: Box, + pub lhs: Expr, /// The operator: `+`. pub op: BinOp, /// The right-hand side of the operation: `b`. - pub rhs: Box, + pub rhs: Expr, } /// A binary operator. @@ -389,7 +405,7 @@ pub struct CallExpr { /// The source code location. pub span: Span, /// The function to call. - pub callee: Box, + pub callee: Expr, /// Whether the call is wide, that is, capturing the template behind it. pub wide: bool, /// The arguments to the function. @@ -475,7 +491,7 @@ pub struct WithExpr { /// The source code location. pub span: Span, /// The function to apply the arguments to. - pub callee: Box, + pub callee: Expr, /// The arguments to apply to the function. pub args: CallArgs, } @@ -488,7 +504,7 @@ pub struct LetExpr { /// The binding to assign to. pub binding: Ident, /// The expression the binding is initialized with. - pub init: Option>, + pub init: Option, } /// An import expression: `import a, b, c from "utils.typ"`. @@ -499,7 +515,7 @@ pub struct ImportExpr { /// The items to be imported. pub imports: Imports, /// The location of the importable file. - pub path: Box, + pub path: Expr, } /// The items that ought to be imported from a file. @@ -517,7 +533,7 @@ pub struct IncludeExpr { /// The source code location. pub span: Span, /// The location of the file to be included. - pub path: Box, + pub path: Expr, } /// An if-else expression: `if x { y } else { z }`. @@ -526,11 +542,11 @@ pub struct IfExpr { /// The source code location. pub span: Span, /// The condition which selects the body to evaluate. - pub condition: Box, + pub condition: Expr, /// The expression to evaluate if the condition is true. - pub if_body: Box, + pub if_body: Expr, /// The expression to evaluate if the condition is false. - pub else_body: Option>, + pub else_body: Option, } /// A while loop expression: `while x { y }`. @@ -539,9 +555,9 @@ pub struct WhileExpr { /// The source code location. pub span: Span, /// The condition which selects whether to evaluate the body. - pub condition: Box, + pub condition: Expr, /// The expression to evaluate while the condition is true. - pub body: Box, + pub body: Expr, } /// A for loop expression: `for x in y { z }`. @@ -552,9 +568,9 @@ pub struct ForExpr { /// The pattern to assign to. pub pattern: ForPattern, /// The expression to iterate over. - pub iter: Box, + pub iter: Expr, /// The expression to evaluate for each iteration. - pub body: Box, + pub body: Expr, } /// A pattern in a for loop. diff --git a/src/syntax/node.rs b/src/syntax/node.rs index 881752a6d..2ca861dcf 100644 --- a/src/syntax/node.rs +++ b/src/syntax/node.rs @@ -3,10 +3,10 @@ use super::*; /// A syntax node, encompassing a single logical entity of parsed source code. #[derive(Debug, Clone, PartialEq)] pub enum SyntaxNode { - /// Plain text. - Text(EcoString), /// Whitespace containing less than two newlines. Space, + /// Plain text. + Text(EcoString), /// A forced line break: `\`. Linebreak(Span), /// A paragraph break: Two or more newlines. @@ -16,13 +16,13 @@ pub enum SyntaxNode { /// Emphasized text was enabled / disabled: `_`. Emph(Span), /// A raw block with optional syntax highlighting: `` `...` ``. - Raw(RawNode), + Raw(Box), /// A section heading: `= Introduction`. - Heading(HeadingNode), + Heading(Box), /// An item in an unordered list: `- ...`. - List(ListItem), + List(Box), /// An item in an enumeration (ordered list): `1. ...`. - Enum(EnumItem), + Enum(Box), /// An expression. Expr(Expr), } diff --git a/src/syntax/token.rs b/src/syntax/token.rs index 567782e72..a4d1867a8 100644 --- a/src/syntax/token.rs +++ b/src/syntax/token.rs @@ -138,7 +138,7 @@ pub enum Token<'s> { /// A percentage: `50%`. /// /// _Note_: `50%` is stored as `50.0` here, as in the corresponding - /// [literal](super::Expr::Percent). + /// [literal](super::Lit::Percent). Percent(f64), /// A fraction unit: `3fr`. Fraction(f64), diff --git a/src/syntax/visit.rs b/src/syntax/visit.rs index e39d1f23d..0a18271dd 100644 --- a/src/syntax/visit.rs +++ b/src/syntax/visit.rs @@ -86,8 +86,8 @@ impl_visitors! { visit_node(v, node: SyntaxNode) { match node { - SyntaxNode::Text(_) => {} SyntaxNode::Space => {} + SyntaxNode::Text(_) => {} SyntaxNode::Linebreak(_) => {} SyntaxNode::Parbreak(_) => {} SyntaxNode::Strong(_) => {} @@ -114,17 +114,8 @@ impl_visitors! { visit_expr(v, expr: Expr) { match expr { - Expr::None(_) => {} - Expr::Auto(_) => {} - Expr::Bool(_, _) => {} - Expr::Int(_, _) => {} - Expr::Float(_, _) => {} - Expr::Length(_, _, _) => {} - Expr::Angle(_, _, _) => {} - Expr::Percent(_, _) => {} - Expr::Fractional(_, _) => {} - Expr::Str(_, _) => {} Expr::Ident(_) => {} + Expr::Lit(_) => {}, Expr::Array(e) => v.visit_array(e), Expr::Dict(e) => v.visit_dict(e), Expr::Template(e) => v.visit_template(e),