Skip to content

Commit ba3ef8e

Browse files
committed
refactor(visitor): move visitors to their own crate.
1 parent f44bfa1 commit ba3ef8e

File tree

9 files changed

+97
-71
lines changed

9 files changed

+97
-71
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ fuse_common = { version = "0.0.0", path = "crates/fuse-common" }
1818
fuse_common_proc = { version = "0.0.0", path = "crates/fuse-common-proc" }
1919
fuse_parser = { version = "0.0.0", path = "crates/fuse-parser" }
2020
fuse_semantic = { version = "0.0.0", path = "crates/fuse-semantic" }
21+
fuse_visitor = { version = "0.0.0", path = "crates/fuse-visitor" }
2122
fusec = { version = "0.0.0", path = "crates/fusec" }
2223

2324
thiserror = { version = "1.0" }

crates/fuse-ast/src/ast.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use fuse_common::{ReferenceId, Span};
1+
use fuse_common::{ReferenceType, Span};
22
use fuse_common_proc::serializable;
33
use std::{cell::Cell, rc::Rc};
44

@@ -185,7 +185,7 @@ pub enum InterpolationFormat {
185185
pub struct Identifier {
186186
pub span: Span,
187187
pub name: Atom,
188-
pub reference: Cell<Option<ReferenceId>>,
188+
pub reference: Cell<Option<ReferenceType>>,
189189
}
190190

191191
#[serializable]

crates/fuse-ast/src/lib.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
mod ast;
21
mod ast_factory;
32
mod precedence;
4-
mod visit;
3+
4+
pub mod ast;
55

66
pub use ast::*;
77
pub use ast_factory::*;
88
pub use precedence::*;
9-
pub use visit::*;

crates/fuse-common/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
mod debug;
12
mod span;
23
mod span_view;
3-
mod debug;
44

55
pub use span::*;
66
pub use span_view::*;
77

8-
pub type ReferenceId = usize;
8+
pub type ReferenceType = usize;

crates/fuse-semantic/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ edition.workspace = true
1010
[dependencies]
1111
fuse_ast = { workspace = true }
1212
fuse_common = { workspace = true }
13+
fuse_visitor = { workspace = true }

crates/fuse-semantic/src/lib.rs

+23-18
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
use std::collections::HashMap;
22

3-
use fuse_ast::{
4-
walk_binding_pattern, walk_function, walk_variable_declaration, Atom, BindingPattern,
5-
BindingPatternKind, Chunk, Identifier, VariableDeclaration, Visitor,
6-
};
7-
use fuse_common::ReferenceId;
3+
use fuse_ast::{Atom, BindingPattern, BindingPatternKind, Chunk, Identifier, VariableDeclaration};
4+
use fuse_common::ReferenceType;
5+
use fuse_visitor::{walk_binding_pattern, walk_function, walk_variable_declaration, Visitor};
86

97
#[derive(Debug, PartialEq, Clone, Copy)]
10-
struct ScopeId(ReferenceId);
8+
struct ScopeId(ReferenceType);
119

1210
impl ScopeId {
1311
#[inline(always)]
14-
const fn as_index(self) -> ReferenceId {
12+
const fn as_index(self) -> ReferenceType {
1513
self.0
1614
}
1715

@@ -21,24 +19,24 @@ impl ScopeId {
2119
}
2220
}
2321

24-
impl PartialEq<ReferenceId> for ScopeId {
25-
fn eq(&self, other: &ReferenceId) -> bool {
22+
impl PartialEq<ReferenceType> for ScopeId {
23+
fn eq(&self, other: &ReferenceType) -> bool {
2624
self.0 == *other
2725
}
2826
}
2927

30-
struct IdentifierMap(HashMap<Atom, ReferenceId>);
28+
struct IdentifierMap(HashMap<Atom, ReferenceType>);
3129

3230
impl IdentifierMap {
3331
fn new() -> Self {
3432
Self(HashMap::new())
3533
}
3634

37-
fn insert(&mut self, atom: Atom, ref_id: ReferenceId) -> Option<ReferenceId> {
35+
fn insert(&mut self, atom: Atom, ref_id: ReferenceType) -> Option<ReferenceType> {
3836
self.0.insert(atom, ref_id)
3937
}
4038

41-
fn get(&self, atom: &Atom) -> Option<ReferenceId> {
39+
fn get(&self, atom: &Atom) -> Option<ReferenceType> {
4240
self.0.get(atom).map(|r| r.clone())
4341
}
4442
}
@@ -80,7 +78,7 @@ impl ScopeTree {
8078

8179
/// Get an identifier reference from current scope or its parents.
8280
/// This function is implemented using loops instead of recursion.
83-
fn identifier_reference(&mut self, atom: &Atom) -> Option<ReferenceId> {
81+
fn identifier_reference(&mut self, atom: &Atom) -> Option<ReferenceType> {
8482
let mut scope_id = self.current;
8583
let mut reference;
8684
loop {
@@ -95,9 +93,13 @@ impl ScopeTree {
9593
reference
9694
}
9795

98-
/// Set a `ReferenceId` for the given identifier's `Atom` in the current scope.
99-
/// Would return the last `ReferenceId` if we are shadowing it.
100-
fn set_identifier_reference(&mut self, atom: Atom, ref_id: ReferenceId) -> Option<ReferenceId> {
96+
/// Set a `ReferenceType` for the given identifier's `Atom` in the current scope.
97+
/// Would return the last `ReferenceType` if we are shadowing it.
98+
fn set_identifier_reference(
99+
&mut self,
100+
atom: Atom,
101+
ref_id: ReferenceType,
102+
) -> Option<ReferenceType> {
101103
self.identifier_maps[self.current.as_index()].insert(atom, ref_id)
102104
}
103105

@@ -122,7 +124,7 @@ pub struct Semantic<'ast> {
122124
source: &'ast str,
123125
chunk: &'ast Chunk,
124126
scope: ScopeTree,
125-
last_reference: ReferenceId,
127+
last_reference: ReferenceType,
126128
}
127129

128130
impl<'ast> Semantic<'ast> {
@@ -165,7 +167,10 @@ impl<'ast> Visitor<'ast> for Semantic<'ast> {
165167
}
166168

167169
fn visit_identifier(&mut self, ident: &Identifier) {
168-
self.reference_identifier(ident);
170+
let refer = unsafe { ident.reference.as_ptr().as_ref() };
171+
if refer.is_none() {
172+
self.reference_identifier(ident);
173+
}
169174
}
170175

171176
fn visit_variable_declaration(&mut self, decl: &'ast VariableDeclaration) {

crates/fuse-visitor/Cargo.toml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "fuse_visitor"
3+
version = "0.0.0"
4+
authors.workspace = true
5+
license.workspace = true
6+
repository.workspace = true
7+
edition.workspace = true
8+
9+
[dependencies]
10+
fuse_ast = { workspace = true }

crates/fuse-visitor/src/lib.rs

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
mod visitor;
2+
mod visitor_mut;
3+
4+
pub use visitor::*;
5+
pub use visitor_mut::*;
6+
7+
/// Placeholder macro for visiting, It is used instead of calling visitor methods directly.
8+
/// Would be useful if we need some operation to happen for every visit.
9+
#[macro_export]
10+
macro_rules! visit {
11+
($expr:expr) => {
12+
$expr
13+
};
14+
}
15+
16+
#[macro_export]
17+
macro_rules! visit_list {
18+
($visitor:ident.$method:ident($list:expr $(, $($extra_args:expr), *)?)) => {
19+
for elem in $list {
20+
visit!($visitor.$method(elem $(, $($extra_args),*)?))
21+
}
22+
};
23+
}
24+
25+
#[macro_export]
26+
macro_rules! visit_scope {
27+
($visitor:ident => $block:block) => {
28+
$visitor.enter_scope();
29+
$block
30+
$visitor.leave_scope();
31+
};
32+
}
33+

crates/fuse-ast/src/visit.rs crates/fuse-visitor/src/visitor.rs

+23-46
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,8 @@
11
// based on https://rust-unofficial.github.io/patterns/patterns/behavioural/visitor.html
22
// and https://github.com/rust-lang/rust/blob/5bc7b9ac8ace5312e1d2cdc2722715cf58d4f926/compiler/rustc_ast_ir/src/visit.rs
33

4-
use crate::ast::*;
5-
6-
/// Placeholder macro for visiting, It is used instead of calling visitor methods directly.
7-
/// Would be useful if we need some operation to happen for every visit.
8-
macro_rules! visit {
9-
($expr:expr) => {
10-
$expr
11-
};
12-
}
13-
14-
macro_rules! visit_list {
15-
($visitor:ident.$method:ident($list:expr $(, $($extra_args:expr), *)?)) => {
16-
for elem in $list {
17-
visit!($visitor.$method(elem $(, $($extra_args),*)?))
18-
}
19-
};
20-
}
21-
22-
macro_rules! visit_scope {
23-
($visitor:ident => $block:block) => {
24-
$visitor.enter_scope();
25-
$block
26-
$visitor.leave_scope();
27-
};
28-
}
4+
use fuse_ast::ast::*;
5+
use crate::{visit, visit_scope, visit_list};
296

307
pub trait Visitor<'ast>: Sized {
318
fn enter_scope(&mut self) {}
@@ -41,37 +18,37 @@ pub trait Visitor<'ast>: Sized {
4118
}
4219

4320
fn visit_statement(&mut self, statement: &'ast Statement) {
44-
walk_statement(self, &statement)
21+
walk_statement(self, statement)
4522
}
4623

4724
fn visit_variable_declaration(&mut self, decl: &'ast VariableDeclaration) {
48-
walk_variable_declaration(self, &decl)
25+
walk_variable_declaration(self, decl)
4926
}
5027

5128
fn visit_function_declaration(&mut self, decl: &'ast Function) {
52-
walk_function(self, &decl)
29+
walk_function(self, decl)
5330
}
5431

5532
fn visit_enum_declaration(&mut self, decl: &'ast EnumDeclaration) {
56-
walk_enum_declaration(self, &decl)
33+
walk_enum_declaration(self, decl)
5734
}
5835

5936
fn visit_enum_variant(&mut self, var: &'ast EnumVariant) {
60-
walk_enum_variant(self, &var)
37+
walk_enum_variant(self, var)
6138
}
6239

6340
fn visit_struct_declaration(&mut self, decl: &'ast StructDeclaration) {
64-
walk_struct_declaration(self, &decl)
41+
walk_struct_declaration(self, decl)
6542
}
6643

6744
fn visit_struct_field(&mut self, field: &'ast StructField) {
68-
walk_struct_field(self, &field)
45+
walk_struct_field(self, field)
6946
}
7047

7148
fn visit_visibility_modifier(&mut self, _: &'ast VisibilityModifier) {}
7249

7350
fn visit_expression(&mut self, expression: &'ast Expression) {
74-
walk_expression(self, &expression)
51+
walk_expression(self, expression)
7552
}
7653

7754
fn visit_number_literal(&mut self, _: &'ast NumberLiteral) {}
@@ -83,31 +60,31 @@ pub trait Visitor<'ast>: Sized {
8360
fn visit_identifier(&mut self, _: &'ast Identifier) {}
8461

8562
fn visit_function(&mut self, func: &'ast Function) {
86-
walk_function(self, &func)
63+
walk_function(self, func)
8764
}
8865

8966
fn visit_function_signature(&mut self, sign: &'ast FunctionSignature) {
90-
walk_function_signature(self, &sign)
67+
walk_function_signature(self, sign)
9168
}
9269

9370
fn visit_function_parameters(&mut self, params: &'ast FunctionParameters) {
94-
walk_function_parameters(self, &params)
71+
walk_function_parameters(self, params)
9572
}
9673

9774
fn visit_function_parameter(&mut self, param: &'ast FunctionParameter) {
98-
walk_function_parameter(self, &param)
75+
walk_function_parameter(self, param)
9976
}
10077

10178
fn visit_function_body(&mut self, body: &'ast FunctionBody) {
102-
walk_function_body(self, &body)
79+
walk_function_body(self, body)
10380
}
10481

10582
fn visit_if(&mut self, r#if: &'ast If) {
106-
walk_if(self, &r#if)
83+
walk_if(self, r#if)
10784
}
10885

10986
fn visit_else(&mut self, r#else: &'ast Else) {
110-
walk_else(self, &r#else)
87+
walk_else(self, r#else)
11188
}
11289

11390
fn visit_unary_operator(&mut self, op: &'ast UnaryOperator) {
@@ -151,27 +128,27 @@ pub trait Visitor<'ast>: Sized {
151128
}
152129

153130
fn visit_binding_pattern(&mut self, pattern: &'ast BindingPattern) {
154-
walk_binding_pattern(self, &pattern)
131+
walk_binding_pattern(self, pattern)
155132
}
156133

157134
fn visit_binding_identifier(&mut self, pattern: &'ast BindingIdentifier) {
158-
walk_binding_identifier(self, &pattern)
135+
walk_binding_identifier(self, pattern)
159136
}
160137

161138
fn visit_binding_rest(&mut self, arg: &'ast BindingRest) {
162-
walk_binding_rest(self, &arg)
139+
walk_binding_rest(self, arg)
163140
}
164141

165142
fn visit_key_value_argument(&mut self, arg: &'ast KeyValueArgument) {
166-
walk_key_value_argument(self, &arg)
143+
walk_key_value_argument(self, arg)
167144
}
168145

169146
fn visit_spread_argument(&mut self, arg: &'ast SpreadArgument) {
170-
walk_spread_argument(self, &arg)
147+
walk_spread_argument(self, arg)
171148
}
172149

173150
fn visit_type_annotation(&mut self, annotation: &'ast TypeAnnotation) {
174-
walk_type_annotation(self, &annotation)
151+
walk_type_annotation(self, annotation)
175152
}
176153
}
177154

0 commit comments

Comments
 (0)