Skip to content

Commit c971494

Browse files
committed
feat(ast): add partial implementation for Visitor trait.
1 parent 1b8ab76 commit c971494

File tree

2 files changed

+174
-4
lines changed

2 files changed

+174
-4
lines changed

crates/fuse-ast/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ mod visit;
66
pub use ast::*;
77
pub use ast_factory::*;
88
pub use precedence::*;
9+
pub use visit::*;

crates/fuse-ast/src/visit.rs

+173-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
// based on https://rust-unofficial.github.io/patterns/patterns/behavioural/visitor.html
2+
// and https://github.com/rust-lang/rust/blob/5bc7b9ac8ace5312e1d2cdc2722715cf58d4f926/compiler/rustc_ast_ir/src/visit.rs
23

34
use crate::ast::*;
45

6+
macro_rules! visit {
7+
($expr:expr) => {
8+
$expr
9+
};
10+
}
11+
512
macro_rules! visit_list {
6-
($visitor:ident, $method:ident, $list:expr) => {
7-
todo!()
13+
($visitor:ident, $method:ident, $list:expr $(, $($extra_args:expr), *)?) => {
14+
for elem in $list {
15+
visit!($visitor.$method(elem $(, $($extra_args),*)?))
16+
}
817
};
918
}
1019

@@ -13,15 +22,175 @@ pub trait Visitor<'ast>: Sized {
1322
walk_block(self, &chunk.body)
1423
}
1524

25+
fn visit_block(&mut self, block: &'ast Block) {
26+
walk_block(self, block)
27+
}
28+
1629
fn visit_statement(&mut self, statement: &'ast Statement) {
1730
walk_statement(self, &statement)
1831
}
32+
33+
fn visit_expression(&mut self, expression: &'ast Expression) {
34+
walk_expression(self, &expression)
35+
}
36+
37+
fn visit_number_literal(&mut self, _: &'ast NumberLiteral) {}
38+
39+
fn visit_string_literal(&mut self, _: &'ast StringLiteral) {}
40+
41+
fn visit_boolean_literal(&mut self, _: &'ast BooleanLiteral) {}
42+
43+
fn visit_identifier(&mut self, _: &'ast Identifier) {}
44+
45+
fn visit_function(&mut self, func: &'ast Function) {
46+
walk_function(self, &func)
47+
}
48+
49+
fn visit_function_signature(&mut self, sign: &'ast FunctionSignature) {
50+
walk_function_signature(self, &sign)
51+
}
52+
53+
fn visit_function_parameters(&mut self, params: &'ast FunctionParameters) {
54+
walk_function_parameters(self, &params)
55+
}
56+
57+
fn visit_function_parameter(&mut self, param: &'ast FunctionParameter) {
58+
walk_function_parameter(self, &param)
59+
}
60+
61+
fn visit_function_body(&mut self, body: &'ast FunctionBody) {
62+
walk_function_body(self, &body)
63+
}
64+
65+
fn visit_binding_pattern(&mut self, pattern: &'ast BindingPattern) {
66+
walk_binding_pattern(self, &pattern)
67+
}
68+
69+
fn visit_binding_identifier(&mut self, pattern: &'ast BindingIdentifier) {
70+
walk_binding_identifier(self, &pattern)
71+
}
72+
73+
fn visit_binding_rest(&mut self, rest: &'ast BindingRest) {
74+
walk_binding_rest(self, &rest)
75+
}
76+
77+
fn visit_type_annotation(&mut self, annotation: &'ast TypeAnnotation) {
78+
walk_type_annotation(self, &annotation)
79+
}
1980
}
2081

2182
pub fn walk_block<'ast, V: Visitor<'ast>>(visitor: &mut V, block: &'ast Block) {
22-
visit_list!(visitor, visit_statement, block.statements)
83+
visit_list!(visitor, visit_statement, &block.statements)
2384
}
2485

2586
pub fn walk_statement<'ast, V: Visitor<'ast>>(visitor: &mut V, statement: &'ast Statement) {
26-
todo!()
87+
match statement {
88+
Statement::Empty(_) => {},
89+
Statement::Expression(expr) => visit!(visitor.visit_expression(expr)),
90+
_ => todo!()
91+
// Statement::VariableDeclaration(Box<VariableDeclaration>),
92+
// Statement::FunctionDeclaration(Box<Function>),
93+
// Statement::EnumDeclaration(Box<EnumDeclaration>),
94+
// Statement::StructDeclaration(Box<StructDeclaration>),
95+
// Statement::ImplStatement(Box<ImplStatement>),
96+
}
2797
}
98+
99+
pub fn walk_expression<'ast, V: Visitor<'ast>>(visitor: &mut V, expression: &'ast Expression) {
100+
match expression {
101+
Expression::NumberLiteral(lit) => visit!(visitor.visit_number_literal(lit)),
102+
Expression::StringLiteral(lit) => visit!(visitor.visit_string_literal(lit)),
103+
Expression::BooleanLiteral(lit) => visit!(visitor.visit_boolean_literal(lit)),
104+
Expression::Identifier(ident) => visit!(visitor.visit_identifier(ident)),
105+
Expression::Function(func) => visit!(visitor.visit_function(func)),
106+
107+
// Expression::If(e),
108+
// Expression::UnaryOperator(e),
109+
// Expression::BinaryOperator(e),
110+
// Expression::ArrayExpression(e),
111+
// Expression::TupleExpression(e),
112+
// Expression::ParenthesizedExpression(e),
113+
// Expression::CallExpression(e),
114+
// Expression::TableConstructionExpression(e),
115+
// Expression::StructConstructionExpression(e),
116+
_ => todo!(),
117+
}
118+
}
119+
120+
pub fn walk_function<'ast, V: Visitor<'ast>>(visitor: &mut V, func: &'ast Function) {
121+
visit!(visitor.visit_function_signature(&func.signature));
122+
visit!(visitor.visit_function_body(&func.body));
123+
}
124+
125+
pub fn walk_function_signature<'ast, V: Visitor<'ast>>(
126+
visitor: &mut V,
127+
sign: &'ast FunctionSignature,
128+
) {
129+
if let Some(ident) = &sign.identifier {
130+
visit!(visitor.visit_identifier(ident));
131+
}
132+
visit!(visitor.visit_function_parameters(&sign.params));
133+
if let Some(annotation) = &sign.return_type {
134+
visit!(visitor.visit_type_annotation(annotation));
135+
}
136+
}
137+
138+
pub fn walk_function_parameters<'ast, V: Visitor<'ast>>(
139+
visitor: &mut V,
140+
params: &'ast FunctionParameters,
141+
) {
142+
for param in &params.items {
143+
visit!(visitor.visit_function_parameter(param))
144+
}
145+
if let Some(rest) = &params.rest {
146+
visit!(visitor.visit_binding_rest(rest))
147+
}
148+
}
149+
150+
pub fn walk_function_parameter<'ast, V: Visitor<'ast>>(
151+
visitor: &mut V,
152+
param: &'ast FunctionParameter,
153+
) {
154+
visit!(visitor.visit_binding_pattern(&param.pattern))
155+
}
156+
157+
pub fn walk_function_body<'ast, V: Visitor<'ast>>(visitor: &mut V, body: &'ast FunctionBody) {
158+
match body {
159+
FunctionBody::Block(block) => visit!(visitor.visit_block(block)),
160+
FunctionBody::Expression(expr) => visit!(visitor.visit_expression(expr)),
161+
}
162+
}
163+
164+
pub fn walk_binding_pattern<'ast, V: Visitor<'ast>>(
165+
visitor: &mut V,
166+
pattern: &'ast BindingPattern,
167+
) {
168+
match &pattern.kind {
169+
BindingPatternKind::Identifier(patt) => {
170+
visit!(visitor.visit_binding_identifier(patt))
171+
}
172+
_ => todo!(),
173+
}
174+
}
175+
176+
pub fn walk_binding_identifier<'ast, V: Visitor<'ast>>(
177+
visitor: &mut V,
178+
pattern: &'ast BindingIdentifier,
179+
) {
180+
visit!(visitor.visit_identifier(&pattern.identifier))
181+
}
182+
183+
pub fn walk_binding_rest<'ast, V: Visitor<'ast>>(visitor: &mut V, rest: &'ast BindingRest) {
184+
visit!(visitor.visit_binding_identifier(&rest.binding));
185+
if let Some(annotation) = &rest.type_annotation {
186+
visit!(visitor.visit_type_annotation(annotation))
187+
};
188+
}
189+
190+
pub fn walk_type_annotation<'ast, V: Visitor<'ast>>(
191+
visitor: &mut V,
192+
annotation: &'ast TypeAnnotation,
193+
) {
194+
}
195+
196+
pub fn walk_template<'ast, V: Visitor<'ast>>(visitor: &mut V, expression: &'ast Expression) {}

0 commit comments

Comments
 (0)