summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-06-30 11:04:53 +0200
committerGitHub <noreply@github.com>2021-06-30 11:04:53 +0200
commit45812b700114a51f0ee21e31f4454cde3729eaf5 (patch)
tree435e5a0ade7dc2cbf9199418c618846bb655e957 /src
parent1c43d8af12a8d318fb681713d0e66eb754485589 (diff)
parentb2fb42cc7019b0269e892c4e39c52557252fecf9 (diff)
Merge pull request #35 from typst/wide-calls
Wide calls
Diffstat (limited to 'src')
-rw-r--r--src/eval/capture.rs2
-rw-r--r--src/exec/mod.rs14
-rw-r--r--src/library/layout.rs25
-rw-r--r--src/library/text.rs22
-rw-r--r--src/parse/mod.rs86
-rw-r--r--src/parse/tokens.rs5
-rw-r--r--src/syntax/expr.rs4
-rw-r--r--src/syntax/token.rs7
-rw-r--r--src/syntax/visit.rs225
9 files changed, 234 insertions, 156 deletions
diff --git a/src/eval/capture.rs b/src/eval/capture.rs
index 64275e93..10f7ec83 100644
--- a/src/eval/capture.rs
+++ b/src/eval/capture.rs
@@ -1,7 +1,7 @@
use std::rc::Rc;
use super::{Scope, Scopes, Value};
-use crate::syntax::visit::{visit_expr, Visit};
+use crate::syntax::visit::{immutable::visit_expr, Visit};
use crate::syntax::{Expr, Ident};
/// A visitor that captures variable slots.
diff --git a/src/exec/mod.rs b/src/exec/mod.rs
index fea6de33..882f1d0b 100644
--- a/src/exec/mod.rs
+++ b/src/exec/mod.rs
@@ -72,10 +72,10 @@ impl Exec for syntax::RawNode {
ctx.parbreak();
}
- let snapshot = ctx.state.clone();
+ let snapshot = Rc::clone(&ctx.state.font);
ctx.set_monospace();
ctx.push_text(&self.text);
- ctx.state = snapshot;
+ ctx.state.font = snapshot;
if self.block {
ctx.parbreak();
@@ -85,16 +85,17 @@ impl Exec for syntax::RawNode {
impl ExecWithMap for syntax::HeadingNode {
fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) {
+ ctx.parbreak();
+
let snapshot = ctx.state.clone();
let font = ctx.state.font_mut();
-
let upscale = 1.6 - 0.1 * self.level as f64;
font.size *= upscale;
font.strong = true;
self.body.exec_with_map(ctx, map);
-
ctx.state = snapshot;
+
ctx.parbreak();
}
}
@@ -113,8 +114,6 @@ impl ExecWithMap for syntax::EnumItem {
}
fn exec_item(ctx: &mut ExecContext, label: String, body: &syntax::Tree, map: &ExprMap) {
- ctx.parbreak();
-
let label = ctx.exec_stack(|ctx| ctx.push_text(label));
let body = ctx.exec_tree_stack(body, map);
let stack = StackNode {
@@ -128,7 +127,6 @@ fn exec_item(ctx: &mut ExecContext, label: String, body: &syntax::Tree, map: &Ex
};
ctx.push_into_stack(stack);
- ctx.parbreak();
}
impl Exec for Value {
@@ -172,6 +170,8 @@ impl Exec for TemplateNode {
impl Exec for TemplateFunc {
fn exec(&self, ctx: &mut ExecContext) {
+ let snapshot = ctx.state.clone();
self(ctx);
+ ctx.state = snapshot;
}
}
diff --git a/src/library/layout.rs b/src/library/layout.rs
index 08924bad..4903077b 100644
--- a/src/library/layout.rs
+++ b/src/library/layout.rs
@@ -20,7 +20,7 @@ pub fn page(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
let right = args.named(ctx, "right");
let bottom = args.named(ctx, "bottom");
let flip = args.named(ctx, "flip");
- let body = args.eat::<TemplateValue>(ctx);
+ let body = args.expect::<TemplateValue>(ctx, "body").unwrap_or_default();
Value::template(move |ctx| {
let snapshot = ctx.state.clone();
@@ -66,13 +66,10 @@ pub fn page(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
}
ctx.pagebreak(false, true, span);
+ body.exec(ctx);
- if let Some(body) = &body {
- // TODO: Restrict body to a single page?
- body.exec(ctx);
- ctx.state = snapshot;
- ctx.pagebreak(true, false, span);
- }
+ ctx.state = snapshot;
+ ctx.pagebreak(true, false, span);
})
}
@@ -111,7 +108,7 @@ pub fn align(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
let second = args.eat::<AlignValue>(ctx);
let mut horizontal = args.named::<AlignValue>(ctx, "horizontal");
let mut vertical = args.named::<AlignValue>(ctx, "vertical");
- let body = args.eat::<TemplateValue>(ctx);
+ let body = args.expect::<TemplateValue>(ctx, "body").unwrap_or_default();
for value in first.into_iter().chain(second) {
match value.axis() {
@@ -126,23 +123,19 @@ pub fn align(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
}
Value::template(move |ctx| {
- let snapshot = ctx.state.clone();
-
if let Some(horizontal) = horizontal {
ctx.state.aligns.cross = horizontal.to_align(ctx.state.lang.dir);
}
if let Some(vertical) = vertical {
- ctx.state.aligns.main = vertical.to_align(Dir::TTB);
- if ctx.state.aligns.main != snapshot.aligns.main {
+ let new = vertical.to_align(Dir::TTB);
+ if ctx.state.aligns.main != new {
+ ctx.state.aligns.main = new;
ctx.parbreak();
}
}
- if let Some(body) = &body {
- body.exec(ctx);
- ctx.state = snapshot;
- }
+ body.exec(ctx);
})
}
diff --git a/src/library/text.rs b/src/library/text.rs
index 6a2fe9bb..28ca2bd8 100644
--- a/src/library/text.rs
+++ b/src/library/text.rs
@@ -17,10 +17,9 @@ pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
let serif = args.named(ctx, "serif");
let sans_serif = args.named(ctx, "sans-serif");
let monospace = args.named(ctx, "monospace");
- let body = args.eat::<TemplateValue>(ctx);
+ let body = args.expect::<TemplateValue>(ctx, "body").unwrap_or_default();
Value::template(move |ctx| {
- let snapshot = ctx.state.clone();
let font = ctx.state.font_mut();
if let Some(linear) = size {
@@ -67,10 +66,7 @@ pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
font.families_mut().monospace = monospace.clone();
}
- if let Some(body) = &body {
- body.exec(ctx);
- ctx.state = snapshot;
- }
+ body.exec(ctx);
})
}
@@ -161,6 +157,7 @@ pub fn par(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
let spacing = args.named(ctx, "spacing");
let leading = args.named(ctx, "leading");
let word_spacing = args.named(ctx, "word-spacing");
+ let body = args.expect::<TemplateValue>(ctx, "body").unwrap_or_default();
Value::template(move |ctx| {
if let Some(spacing) = spacing {
@@ -176,6 +173,7 @@ pub fn par(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
}
ctx.parbreak();
+ body.exec(ctx);
})
}
@@ -190,6 +188,7 @@ pub fn lang(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
}
None => None,
};
+ let body = args.expect::<TemplateValue>(ctx, "body").unwrap_or_default();
Value::template(move |ctx| {
if let Some(dir) = dir.or(iso) {
@@ -197,6 +196,7 @@ pub fn lang(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
}
ctx.parbreak();
+ body.exec(ctx);
})
}
@@ -232,7 +232,7 @@ fn line_impl(
let position = args.named(ctx, "position");
let strength = args.named::<Linear>(ctx, "strength");
let extent = args.named(ctx, "extent").unwrap_or_default();
- let body = args.eat::<TemplateValue>(ctx);
+ let body = args.expect::<TemplateValue>(ctx, "body").unwrap_or_default();
// Suppress any existing strikethrough if strength is explicitly zero.
let state = strength.map_or(true, |s| !s.is_zero()).then(|| {
@@ -245,13 +245,7 @@ fn line_impl(
});
Value::template(move |ctx| {
- let snapshot = ctx.state.clone();
-
*substate(ctx.state.font_mut()) = state.clone();
-
- if let Some(body) = &body {
- body.exec(ctx);
- ctx.state = snapshot;
- }
+ body.exec(ctx);
})
}
diff --git a/src/parse/mod.rs b/src/parse/mod.rs
index 381d44e2..e8e16803 100644
--- a/src/parse/mod.rs
+++ b/src/parse/mod.rs
@@ -15,6 +15,7 @@ pub use tokens::*;
use std::rc::Rc;
use crate::diag::Pass;
+use crate::syntax::visit::{mutable::visit_expr, VisitMut};
use crate::syntax::*;
/// Parse a string of source code.
@@ -25,7 +26,7 @@ pub fn parse(src: &str) -> Pass<Tree> {
/// Parse a syntax tree.
fn tree(p: &mut Parser) -> Tree {
- tree_while(p, true, |_| true)
+ tree_while(p, true, &mut |_| true)
}
/// Parse a syntax tree that stays right of the column at the start of the next
@@ -38,31 +39,70 @@ fn tree_indented(p: &mut Parser) -> Tree {
});
let column = p.column(p.next_start());
- tree_while(p, false, |p| match p.peek() {
+ tree_while(p, false, &mut |p| match p.peek() {
Some(Token::Space(n)) if n >= 1 => p.column(p.next_end()) >= column,
_ => true,
})
}
/// Parse a syntax tree.
-fn tree_while(
- p: &mut Parser,
- mut at_start: bool,
- mut f: impl FnMut(&mut Parser) -> bool,
-) -> Tree {
+fn tree_while<F>(p: &mut Parser, mut at_start: bool, f: &mut F) -> Tree
+where
+ F: FnMut(&mut Parser) -> bool,
+{
+ /// Visitor that adds a recursively parsed rest template to the first wide
+ /// call's argument list and diagnoses all following wide calls.
+ struct WideVisitor<'a, 's, F> {
+ p: &'a mut Parser<'s>,
+ f: &'a mut F,
+ found: bool,
+ }
+
+ impl<'ast, 'a, 's, F> VisitMut<'ast> for WideVisitor<'a, 's, F>
+ where
+ F: FnMut(&mut Parser) -> bool,
+ {
+ fn visit_expr(&mut self, node: &'ast mut Expr) {
+ visit_expr(self, node);
+
+ if let Expr::Call(call) = node {
+ if call.wide {
+ let start = self.p.next_start();
+ let tree = if !self.found {
+ tree_while(self.p, true, self.f)
+ } else {
+ self.p.diag(error!(call.callee.span(), "duplicate wide call"));
+ Tree::default()
+ };
+
+ call.args.items.push(CallArg::Pos(Expr::Template(TemplateExpr {
+ span: self.p.span(start),
+ tree: Rc::new(tree),
+ })));
+
+ self.found = true;
+ }
+ }
+ }
+
+ // Don't recurse into templates.
+ fn visit_template(&mut self, _: &'ast mut TemplateExpr) {}
+ }
+
// We use `at_start` to keep track of whether we are at the start of a line
// or template to know whether things like headings are allowed.
let mut tree = vec![];
while !p.eof() && f(p) {
- if let Some(node) = node(p, &mut at_start) {
- match node {
- Node::Space => {}
- Node::Parbreak(_) => {}
- _ => at_start = false,
+ if let Some(mut node) = node(p, &mut at_start) {
+ at_start &= matches!(node, Node::Space | Node::Parbreak(_));
+ if let Node::Expr(expr) = &mut node {
+ let mut visitor = WideVisitor { p, f, found: false };
+ visitor.visit_expr(expr);
}
tree.push(node);
}
}
+
tree
}
@@ -236,12 +276,13 @@ fn expr_with(p: &mut Parser, atomic: bool, min_prec: usize) -> Option<Expr> {
};
loop {
- // Parenthesis or bracket means this is a function call.
+ // Exclamation mark, parenthesis or bracket means this is a function
+ // call.
if matches!(
p.peek_direct(),
- Some(Token::LeftParen) | Some(Token::LeftBracket),
+ Some(Token::Excl) | Some(Token::LeftParen) | Some(Token::LeftBracket),
) {
- lhs = call(p, lhs);
+ lhs = call(p, lhs)?;
continue;
}
@@ -516,7 +557,9 @@ fn block(p: &mut Parser, scoping: bool) -> Expr {
}
/// Parse a function call.
-fn call(p: &mut Parser, callee: Expr) -> Expr {
+fn call(p: &mut Parser, callee: Expr) -> Option<Expr> {
+ let wide = p.eat_if(Token::Excl);
+
let mut args = match p.peek_direct() {
Some(Token::LeftParen) => {
p.start_group(Group::Paren, TokenMode::Code);
@@ -524,10 +567,14 @@ fn call(p: &mut Parser, callee: Expr) -> Expr {
p.end_group();
args
}
- _ => CallArgs {
+ Some(Token::LeftBracket) => CallArgs {
span: Span::at(callee.span().end),
items: vec![],
},
+ _ => {
+ p.expected_at("argument list", p.prev_end());
+ return None;
+ }
};
if p.peek_direct() == Some(Token::LeftBracket) {
@@ -535,11 +582,12 @@ fn call(p: &mut Parser, callee: Expr) -> Expr {
args.items.push(CallArg::Pos(body));
}
- Expr::Call(CallExpr {
+ Some(Expr::Call(CallExpr {
span: p.span(callee.span().start),
callee: Box::new(callee),
+ wide,
args,
- })
+ }))
}
/// Parse the arguments to a function call.
diff --git a/src/parse/tokens.rs b/src/parse/tokens.rs
index abc3d6a6..4d90dded 100644
--- a/src/parse/tokens.rs
+++ b/src/parse/tokens.rs
@@ -117,7 +117,7 @@ impl<'s> Tokens<'s> {
// Length two.
'=' if self.s.eat_if('=') => Token::EqEq,
- '!' if self.s.eat_if('=') => Token::BangEq,
+ '!' if self.s.eat_if('=') => Token::ExclEq,
'<' if self.s.eat_if('=') => Token::LtEq,
'>' if self.s.eat_if('=') => Token::GtEq,
'+' if self.s.eat_if('=') => Token::PlusEq,
@@ -135,6 +135,7 @@ impl<'s> Tokens<'s> {
'-' => Token::Hyph,
'*' => Token::Star,
'/' => Token::Slash,
+ '!' => Token::Excl,
'=' => Token::Eq,
'<' => Token::Lt,
'>' => Token::Gt,
@@ -750,7 +751,7 @@ mod tests {
t!(Code[" a1"]: "/" => Slash);
t!(Code: "=" => Eq);
t!(Code: "==" => EqEq);
- t!(Code: "!=" => BangEq);
+ t!(Code: "!=" => ExclEq);
t!(Code: "<" => Lt);
t!(Code: "<=" => LtEq);
t!(Code: ">" => Gt);
diff --git a/src/syntax/expr.rs b/src/syntax/expr.rs
index 62f02399..aabff1ea 100644
--- a/src/syntax/expr.rs
+++ b/src/syntax/expr.rs
@@ -295,7 +295,7 @@ impl BinOp {
Token::And => Self::And,
Token::Or => Self::Or,
Token::EqEq => Self::Eq,
- Token::BangEq => Self::Neq,
+ Token::ExclEq => Self::Neq,
Token::Lt => Self::Lt,
Token::LtEq => Self::Leq,
Token::Gt => Self::Gt,
@@ -388,6 +388,8 @@ pub struct CallExpr {
pub span: Span,
/// The function to call.
pub callee: Box<Expr>,
+ /// Whether the call is wide, that is, capturing the template behind it.
+ pub wide: bool,
/// The arguments to the function.
pub args: CallArgs,
}
diff --git a/src/syntax/token.rs b/src/syntax/token.rs
index 3f07bb33..25062264 100644
--- a/src/syntax/token.rs
+++ b/src/syntax/token.rs
@@ -42,12 +42,14 @@ pub enum Token<'s> {
Hyph,
/// A slash: `/`.
Slash,
+ /// An exlamation mark.
+ Excl,
/// A single equals sign: `=`.
Eq,
/// Two equals signs: `==`.
EqEq,
/// An exclamation mark followed by an equals sign: `!=`.
- BangEq,
+ ExclEq,
/// A less-than sign: `<`.
Lt,
/// A less-than sign followed by an equals sign: `<=`.
@@ -227,9 +229,10 @@ impl<'s> Token<'s> {
Self::Plus => "plus",
Self::Hyph => "minus",
Self::Slash => "slash",
+ Self::Excl => "exclamation mark",
Self::Eq => "assignment operator",
Self::EqEq => "equality operator",
- Self::BangEq => "inequality operator",
+ Self::ExclEq => "inequality operator",
Self::Lt => "less-than operator",
Self::LtEq => "less-than or equal operator",
Self::Gt => "greater-than operator",
diff --git a/src/syntax/visit.rs b/src/syntax/visit.rs
index 52418361..657b379a 100644
--- a/src/syntax/visit.rs
+++ b/src/syntax/visit.rs
@@ -1,54 +1,91 @@
-//! Syntax tree traversal.
+//! Mutable and immutable syntax tree traversal.
-use super::*;
+use crate::syntax::*;
-macro_rules! visit {
- ($(fn $name:ident($v:ident $(, $node:ident: &$ty:ty)?) $body:block)*) => {
- /// Traverses the syntax tree.
- pub trait Visit<'ast> {
- $(fn $name(&mut self $(, $node: &'ast $ty)?) {
- $name(self, $($node)?);
- })*
+/// Implement the immutable and the mutable visitor version.
+macro_rules! impl_visitors {
+ ($($name:ident($($tts:tt)*) $body:block)*) => {
+ macro_rules! r {
+ (rc: $x:expr) => { $x.as_ref() };
+ ($x:expr) => { &$x };
+ }
+ impl_visitor! {
+ /// Walk syntax trees immutably.
+ Visit,
+ /// Immutable visitor functions.
+ immutable,
+ [$(($name($($tts)*) $body))*]
+ }
+
+ macro_rules! r {
+ (rc: $x:expr) => { std::rc::Rc::make_mut(&mut $x) };
+ ($x:expr) => { &mut $x };
+ }
+
+ impl_visitor! {
+ /// Walk syntax trees mutably.
+ VisitMut,
+ /// Mutable visitor functions.
+ mutable,
+ [$(($name($($tts)*) $body mut))*] mut
+ }
+ };
+}
+
+/// Implement an immutable or mutable visitor.
+macro_rules! impl_visitor {
+ (
+ #[doc = $visit_doc:expr] $visit:ident,
+ #[doc = $module_doc:expr] $module:ident,
+ [$((
+ $name:ident($v:ident, $node:ident: $ty:ty)
+ $body:block
+ $($fmut:tt)?
+ ))*]
+ $($mut:tt)?
+ ) => {
+ #[doc = $visit_doc]
+ pub trait $visit<'ast> {
/// Visit a definition of a binding.
///
/// Bindings are, for example, left-hand side of let expressions,
/// and key/value patterns in for loops.
- fn visit_binding(&mut self, _: &'ast Ident) {}
+ fn visit_binding(&mut self, _: &'ast $($mut)? Ident) {}
/// Visit the entry into a scope.
fn visit_enter(&mut self) {}
/// Visit the exit from a scope.
fn visit_exit(&mut self) {}
- }
- $(visit! {
- @$(concat!("Walk a node of type [`", stringify!($ty), "`]."), )?
- pub fn $name<'ast, V>(
- #[allow(unused)] $v: &mut V
- $(, #[allow(unused)] $node: &'ast $ty)?
- )
- where
- V: Visit<'ast> + ?Sized
- $body
- })*
- };
+ $(fn $name(&mut self, $node: &'ast $($fmut)? $ty) {
+ $module::$name(self, $node);
+ })*
+ }
- (@$doc:expr, $($tts:tt)*) => {
- #[doc = $doc]
- $($tts)*
+ #[doc = $module_doc]
+ pub mod $module {
+ use super::*;
+ $(
+ #[allow(unused_variables)]
+ pub fn $name<'ast, V>($v: &mut V, $node: &'ast $($fmut)? $ty)
+ where
+ V: $visit<'ast> + ?Sized
+ $body
+ )*
+ }
};
}
-visit! {
- fn visit_tree(v, node: &Tree) {
- for node in node {
- v.visit_node(&node);
+impl_visitors! {
+ visit_tree(v, tree: Tree) {
+ for node in tree {
+ v.visit_node(node);
}
}
- fn visit_node(v, node: &Node) {
+ visit_node(v, node: Node) {
match node {
Node::Text(_) => {}
Node::Space => {}
@@ -64,20 +101,20 @@ visit! {
}
}
- fn visit_heading(v, node: &HeadingNode) {
- v.visit_tree(&node.body);
+ visit_heading(v, heading: HeadingNode) {
+ v.visit_tree(r!(rc: heading.body));
}
- fn visit_list(v, node: &ListItem) {
- v.visit_tree(&node.body);
+ visit_list(v, item: ListItem) {
+ v.visit_tree(r!(item.body));
}
- fn visit_enum(v, node: &EnumItem) {
- v.visit_tree(&node.body);
+ visit_enum(v, item: EnumItem) {
+ v.visit_tree(r!(item.body));
}
- fn visit_expr(v, node: &Expr) {
- match node {
+ visit_expr(v, expr: Expr) {
+ match expr {
Expr::None(_) => {}
Expr::Auto(_) => {}
Expr::Bool(_, _) => {}
@@ -109,121 +146,121 @@ visit! {
}
}
- fn visit_array(v, node: &ArrayExpr) {
- for expr in &node.items {
- v.visit_expr(&expr);
+ visit_array(v, array: ArrayExpr) {
+ for expr in r!(array.items) {
+ v.visit_expr(expr);
}
}
- fn visit_dict(v, node: &DictExpr) {
- for named in &node.items {
- v.visit_expr(&named.expr);
+ visit_dict(v, dict: DictExpr) {
+ for named in r!(dict.items) {
+ v.visit_expr(r!(named.expr));
}
}
- fn visit_template(v, node: &TemplateExpr) {
+ visit_template(v, template: TemplateExpr) {
v.visit_enter();
- v.visit_tree(&node.tree);
+ v.visit_tree(r!(rc: template.tree));
v.visit_exit();
}
- fn visit_group(v, node: &GroupExpr) {
- v.visit_expr(&node.expr);
+ visit_group(v, group: GroupExpr) {
+ v.visit_expr(r!(group.expr));
}
- fn visit_block(v, node: &BlockExpr) {
- if node.scoping {
+ visit_block(v, block: BlockExpr) {
+ if block.scoping {
v.visit_enter();
}
- for expr in &node.exprs {
- v.visit_expr(&expr);
+ for expr in r!(block.exprs) {
+ v.visit_expr(expr);
}
- if node.scoping {
+ if block.scoping {
v.visit_exit();
}
}
- fn visit_binary(v, node: &BinaryExpr) {
- v.visit_expr(&node.lhs);
- v.visit_expr(&node.rhs);
+ visit_binary(v, binary: BinaryExpr) {
+ v.visit_expr(r!(binary.lhs));
+ v.visit_expr(r!(binary.rhs));
}
- fn visit_unary(v, node: &UnaryExpr) {
- v.visit_expr(&node.expr);
+ visit_unary(v, unary: UnaryExpr) {
+ v.visit_expr(r!(unary.expr));
}
- fn visit_call(v, node: &CallExpr) {
- v.visit_expr(&node.callee);
- v.visit_args(&node.args);
+ visit_call(v, call: CallExpr) {
+ v.visit_expr(r!(call.callee));
+ v.visit_args(r!(call.args));
}
- fn visit_closure(v, node: &ClosureExpr) {
- for param in node.params.iter() {
+ visit_closure(v, closure: ClosureExpr) {
+ for param in r!(rc: closure.params) {
v.visit_binding(param);
}
- v.visit_expr(&node.body);
+ v.visit_expr(r!(rc: closure.body));
}
- fn visit_args(v, node: &CallArgs) {
- for arg in &node.items {
+ visit_args(v, args: CallArgs) {
+ for arg in r!(args.items) {
v.visit_arg(arg);
}
}
- fn visit_arg(v, node: &CallArg) {
- match node {
- CallArg::Pos(expr) => v.visit_expr(&expr),
- CallArg::Named(named) => v.visit_expr(&named.expr),
+ visit_arg(v, arg: CallArg) {
+ match arg {
+ CallArg::Pos(expr) => v.visit_expr(expr),
+ CallArg::Named(named) => v.visit_expr(r!(named.expr)),
}
}
- fn visit_with(v, node: &WithExpr) {
- v.visit_expr(&node.callee);
- v.visit_args(&node.args);
+ visit_with(v, with_expr: WithExpr) {
+ v.visit_expr(r!(with_expr.callee));
+ v.visit_args(r!(with_expr.args));
}
- fn visit_let(v, node: &LetExpr) {
- if let Some(init) = &node.init {
- v.visit_expr(&init);
+ visit_let(v, let_expr: LetExpr) {
+ if let Some(init) = r!(let_expr.init) {
+ v.visit_expr(init);
}
- v.visit_binding(&node.binding);
+ v.visit_binding(r!(let_expr.binding));
}
- fn visit_if(v, node: &IfExpr) {
- v.visit_expr(&node.condition);
- v.visit_expr(&node.if_body);
- if let Some(body) = &node.else_body {
- v.visit_expr(&body);
+ visit_if(v, if_expr: IfExpr) {
+ v.visit_expr(r!(if_expr.condition));
+ v.visit_expr(r!(if_expr.if_body));
+ if let Some(body) = r!(if_expr.else_body) {
+ v.visit_expr(body);
}
}
- fn visit_while(v, node: &WhileExpr) {
- v.visit_expr(&node.condition);
- v.visit_expr(&node.body);
+ visit_while(v, while_expr: WhileExpr) {
+ v.visit_expr(r!(while_expr.condition));
+ v.visit_expr(r!(while_expr.body));
}
- fn visit_for(v, node: &ForExpr) {
- v.visit_expr(&node.iter);
- match &node.pattern {
+ visit_for(v, for_expr: ForExpr) {
+ v.visit_expr(r!(for_expr.iter));
+ match r!(for_expr.pattern) {
ForPattern::Value(value) => v.visit_binding(value),
ForPattern::KeyValue(key, value) => {
v.visit_binding(key);
v.visit_binding(value);
}
}
- v.visit_expr(&node.body);
+ v.visit_expr(r!(for_expr.body));
}
- fn visit_import(v, node: &ImportExpr) {
- v.visit_expr(&node.path);
- if let Imports::Idents(idents) = &node.imports {
+ visit_import(v, import_expr: ImportExpr) {
+ v.visit_expr(r!(import_expr.path));
+ if let Imports::Idents(idents) = r!(import_expr.imports) {
for ident in idents {
v.visit_binding(ident);
}
}
}
- fn visit_include(v, node: &IncludeExpr) {
- v.visit_expr(&node.path);
+ visit_include(v, include_expr: IncludeExpr) {
+ v.visit_expr(r!(include_expr.path));
}
}