Add depth-first traversal (walk_depth_first) to walk.rs.

This commit is contained in:
Jesse Brault 2025-05-26 12:53:07 -05:00
parent 22deb90c3e
commit d38b30b755
3 changed files with 754 additions and 305 deletions

File diff suppressed because it is too large Load Diff

View File

@ -3,3 +3,4 @@ pub mod children;
pub mod node;
pub mod pretty_print;
pub mod unparse;
mod walk;

145
src/ast/walk.rs Normal file
View File

@ -0,0 +1,145 @@
use crate::ast::children::{NodeInner, NodeRef};
pub fn walk_depth_first<F>(node: &dyn NodeInner, f: &mut F)
where
F: FnMut(NodeRef),
{
use NodeRef::*;
for child in node.children() {
match child {
Identifier(identifier) => walk_depth_first(identifier, f),
FullyQualifiedName(fqn) => {
walk_depth_first(fqn, f);
}
TypeUse(type_use) => walk_depth_first(type_use, f),
PrimitiveTypeUse(primitive_type_use) => walk_depth_first(primitive_type_use, f),
InterfaceOrClassTypeUse(interface_or_class_type_use) => {
walk_depth_first(interface_or_class_type_use, f)
}
TupleTypeUse(tuple_type_use) => walk_depth_first(tuple_type_use, f),
FunctionTypeUse(function_type_use) => walk_depth_first(function_type_use, f),
GenericArguments(generic_arguments) => walk_depth_first(generic_arguments, f),
GenericParameters(generic_parameters) => walk_depth_first(generic_parameters, f),
TupleArguments(tuple_arguments) => walk_depth_first(tuple_arguments, f),
ImplementsList(implements) => walk_depth_first(implements, f),
Parameters(parameters) => walk_depth_first(parameters, f),
Parameter(parameter) => walk_depth_first(parameter, f),
ReturnType(return_type) => walk_depth_first(return_type, f),
References(references) => walk_depth_first(references, f),
UseStatement(use_statement) => walk_depth_first(use_statement, f),
CompilationUnit(compilation_unit) => walk_depth_first(compilation_unit, f),
ModuleLevelDeclaration(module_level_declaration) => {
walk_depth_first(module_level_declaration, f)
}
InterfaceLevelDeclaration(interface_level_declaration) => {
walk_depth_first(interface_level_declaration, f)
}
ClassLevelDeclaration(class_level_declaration) => {
walk_depth_first(class_level_declaration, f)
}
ModuleDeclaration(module_declaration) => walk_depth_first(module_declaration, f),
InterfaceDeclaration(interface_declaration) => {
walk_depth_first(interface_declaration, f)
}
ClassDeclaration(class_declaration) => walk_depth_first(class_declaration, f),
FunctionDefinition(function_definition) => walk_depth_first(function_definition, f),
OperatorFunctionDefinition(operator_function_definition) => {
walk_depth_first(operator_function_definition, f)
}
PlatformFunctionDeclaration(platform_function_declaration) => {
walk_depth_first(platform_function_declaration, f)
}
InterfaceFunctionDeclaration(interface_function_declaration) => {
walk_depth_first(interface_function_declaration, f)
}
InterfaceOperatorFunctionDeclaration(interface_operator_function_declaration) => {
walk_depth_first(interface_operator_function_declaration, f)
}
FunctionBody(function_body) => walk_depth_first(function_body, f),
ClassConstructor(class_constructor) => walk_depth_first(class_constructor, f),
ClassConstructorParameter(class_constructor_parameter) => {
walk_depth_first(class_constructor_parameter, f)
}
PropertyDeclaration(property_declaration) => walk_depth_first(property_declaration, f),
FieldDeclaration(field_declaration) => walk_depth_first(field_declaration, f),
BlockStatement(block) => walk_depth_first(block, f),
Statement(statement) => walk_depth_first(statement, f),
VariableDeclarationStatement(variable_declaration) => {
walk_depth_first(variable_declaration, f)
}
AssignStatement(assign_statement) => walk_depth_first(assign_statement, f),
CallStatement(call_statement) => walk_depth_first(call_statement, f),
ReturnStatement(return_statement) => walk_depth_first(return_statement, f),
IfStatement(if_statement) => walk_depth_first(if_statement, f),
IfElseStatement(if_else_statement) => walk_depth_first(if_else_statement, f),
ElseIfs(else_ifs) => walk_depth_first(else_ifs, f),
ElseBlock(else_block) => walk_depth_first(else_block, f),
WhileStatement(while_statement) => walk_depth_first(while_statement, f),
ForStatement(for_statement) => walk_depth_first(for_statement, f),
Expression(expression) => walk_depth_first(expression, f),
TernaryExpression(ternary_expression) => walk_depth_first(ternary_expression, f),
BinaryExpression(binary_expression) => walk_depth_first(binary_expression, f),
PrefixExpression(prefix_expression) => walk_depth_first(prefix_expression, f),
SuffixExpression(suffix_expression) => walk_depth_first(suffix_expression, f),
CallExpression(call_expression) => walk_depth_first(call_expression, f),
TurboFish(turbo_fish) => walk_depth_first(turbo_fish, f),
CallArguments(call_arguments) => walk_depth_first(call_arguments, f),
CallArgument(call_argument) => walk_depth_first(call_argument, f),
Closure(closure) => walk_depth_first(closure, f),
ClosureCaptures(closure_captures) => walk_depth_first(closure_captures, f),
ClosureCapture(closure_capture) => walk_depth_first(closure_capture, f),
ClosureParameters(closure_parameters) => walk_depth_first(closure_parameters, f),
ClosureParameter(closure_parameter) => walk_depth_first(closure_parameter, f),
ObjectAccess(object_access) => walk_depth_first(object_access, f),
ObjectNavigations(object_navigations) => walk_depth_first(object_navigations, f),
ObjectNavigation(object_navigations) => walk_depth_first(object_navigations, f),
Literal(literal) => walk_depth_first(literal, f),
DString(d_string) => walk_depth_first(d_string, f),
DStringPart(d_string_part) => walk_depth_first(d_string_part, f),
}
}
f(node.as_node_ref());
}
#[cfg(test)]
mod tests {
use crate::ast::build::build_ast;
use crate::ast::children::NodeRef;
use crate::ast::walk::walk_depth_first;
use crate::parser::{DeimosParser, Rule};
use indoc::indoc;
use pest::Parser;
#[test]
fn collect_identifiers() {
let parse_result = DeimosParser::parse(
Rule::CompilationUnit,
indoc! {"
ns greeter;
class Greeter {}
fn main() {
let greeter = Greeter();
}
"},
);
match parse_result {
Ok(cu_pairs) => {
let cu = build_ast("greeter.dm", 0, cu_pairs.into_iter().next().unwrap());
let mut identifier_count = 0;
walk_depth_first(&cu, &mut |node_ref| match node_ref {
NodeRef::Identifier(identifier) => {
dbg!(identifier);
identifier_count += 1;
}
_ => {}
});
assert_eq!(identifier_count, 5);
}
Err(err) => {
panic!("{}", err);
}
}
}
}