Simplify tree visitors

This commit is contained in:
Nikita Lisitsa 2025-12-20 13:20:44 +03:00
parent aee506d102
commit 8c07e1950b
7 changed files with 99 additions and 194 deletions

View file

@ -16,14 +16,7 @@ namespace pslang::ast
template <typename Expression>
void operator()(Expression const & expression)
{
if constexpr (std::is_invocable_v<Visitor, const_expression_visitor_helper &, Expression const &>)
{
visitor(*this, expression);
}
else
{
visitor(expression);
}
visitor(expression);
}
void operator()(literal const & expression)
@ -45,14 +38,7 @@ namespace pslang::ast
template <typename Expression>
void operator()(Expression & expression)
{
if constexpr (std::is_invocable_v<Visitor, expression_visitor_helper &, Expression &>)
{
visitor(*this, expression);
}
else
{
visitor(expression);
}
visitor(expression);
}
void operator()(literal & expression)

View file

@ -16,14 +16,7 @@ namespace pslang::ast
template <typename Statement>
void operator()(Statement const & statement)
{
if constexpr (std::is_invocable_v<Visitor, const_statement_visitor_helper &, Statement const &>)
{
visitor(*this, statement);
}
else
{
visitor(statement);
}
visitor(statement);
}
void operator()(statement const & statement)
@ -46,14 +39,7 @@ namespace pslang::ast
template <typename Statement>
void operator()(Statement & statement)
{
if constexpr (std::is_invocable_v<Visitor, statement_visitor_helper &, Statement &>)
{
visitor(*this, statement);
}
else
{
visitor(statement);
}
visitor(statement);
}
void operator()(statement & statement)

View file

@ -16,14 +16,7 @@ namespace pslang::ast
template <typename Type>
void operator()(Type const & type)
{
if constexpr (std::is_invocable_v<Visitor, const_type_visitor_helper &, Type const &>)
{
visitor(*this, type);
}
else
{
visitor(type);
}
visitor(type);
}
void operator()(types::primitive_type const & type)
@ -45,14 +38,7 @@ namespace pslang::ast
template <typename Type>
void operator()(Type & type)
{
if constexpr (std::is_invocable_v<Visitor, type_visitor_helper &, Type &>)
{
visitor(*this, type);
}
else
{
visitor(type);
}
visitor(type);
}
void operator()(types::primitive_type & type)

View file

@ -41,21 +41,19 @@ namespace pslang::ast
types::print(out, types::primitive_type{type});
}
template <typename Self>
void operator()(Self & self, array_type const & type)
void operator()(array_type const & type)
{
self(*type.element_type);
apply(*this, *type.element_type);
out << "[" << type.size << "]";
}
template <typename Self>
void operator()(Self & self, function_type const & type)
void operator()(function_type const & type)
{
if (type.arguments.size() == 1)
{
self(*type.arguments.front());
apply(*this, *type.arguments.front());
out << " -> ";
self(*type.result);
apply(*this, *type.result);
return;
}
@ -65,10 +63,10 @@ namespace pslang::ast
{
if (!first) out << ", ";
first = false;
self(*argument);
apply(*this, *argument);
}
out << ") -> ";
self(*type.result);
apply(*this, *type.result);
}
void operator()(type_identifier const & type)
@ -82,11 +80,11 @@ namespace pslang::ast
std::ostream & out;
print_options options;
template <typename Self, typename Node>
void child(Self & self, Node const & node)
template <typename Node>
void child(Node const & node)
{
++options.indent_level;
self(node);
apply(*this, node);
--options.indent_level;
}
@ -162,67 +160,60 @@ namespace pslang::ast
out << "identifier { name = \"" << node.name << "\" }\n";
}
template <typename Self>
void operator()(Self & self, unary_operation const & node)
void operator()(unary_operation const & node)
{
put_indent(out, options);
out << node.type << '\n';
child(self, *node.arg1);
child(*node.arg1);
}
template <typename Self>
void operator()(Self & self, binary_operation const & node)
void operator()(binary_operation const & node)
{
put_indent(out, options);
out << node.type << '\n';
child(self, *node.arg1);
child(self, *node.arg2);
child(*node.arg1);
child(*node.arg2);
}
template <typename Self>
void operator()(Self & self, cast_operation const & node)
void operator()(cast_operation const & node)
{
put_indent(out, options);
out << "cast as ";
print(out, *node.type);
out << '\n';
child(self, *node.expression);
child(*node.expression);
}
template <typename Self>
void operator()(Self & self, function_call const & node)
void operator()(function_call const & node)
{
put_indent(out, options);
out << "call\n";
child(self, *node.function);
child(*node.function);
for (auto const & argument : node.arguments)
child(self, *argument);
child(*argument);
}
template <typename Self>
void operator()(Self & self, array const & node)
void operator()(array const & node)
{
put_indent(out, options);
out << "array\n";
for (auto const & element : node.elements)
child(self, *element);
child(*element);
}
template <typename Self>
void operator()(Self & self, array_access const & node)
void operator()(array_access const & node)
{
put_indent(out, options);
out << "array access\n";
child(self, *node.array);
child(self, *node.index);
child(*node.array);
child(*node.index);
}
template <typename Self>
void operator()(Self & self, field_access const & node)
void operator()(field_access const & node)
{
put_indent(out, options);
out << "field access { name = \"" << node.field_name << "\" }\n";
child(self, *node.object);
child(*node.object);
}
};
@ -231,11 +222,11 @@ namespace pslang::ast
std::ostream & out;
print_options options;
template <typename Self, typename Node>
void child(Self & self, Node const & node)
template <typename Node>
void child(Node const & node)
{
++options.indent_level;
self(node);
ast::apply(*this, node);
--options.indent_level;
}
@ -244,17 +235,15 @@ namespace pslang::ast
print(out, *node, options);
}
template <typename Self>
void operator()(Self & self, assignment const & node)
void operator()(assignment const & node)
{
put_indent(out, options);
out << "assignment\n";
child(self, node.lhs);
child(self, node.rhs);
child(node.lhs);
child(node.rhs);
}
template <typename Self>
void operator()(Self & self, variable_declaration const & node)
void operator()(variable_declaration const & node)
{
put_indent(out, options);
out << "variable declaration { category = " << node.category << ", name = \"" << node.name << "\"";
@ -264,15 +253,14 @@ namespace pslang::ast
print(out, *node.type);
}
out << " }\n";
child(self, node.initializer);
child(node.initializer);
}
template <typename Self>
void operator()(Self & self, if_block const & node)
void operator()(if_block const & node)
{
put_indent(out, options);
out << "if\n";
child(self, node.condition);
child(node.condition);
}
void operator()(else_block const & node)
@ -281,16 +269,14 @@ namespace pslang::ast
out << "else\n";
}
template <typename Self>
void operator()(Self & self, else_if_block const & node)
void operator()(else_if_block const & node)
{
put_indent(out, options);
out << "else if\n";
child(self, node.condition);
child(node.condition);
}
template <typename Self>
void operator()(Self & self, if_chain const & node)
void operator()(if_chain const & node)
{
put_indent(out, options);
out << "if chain\n";
@ -300,7 +286,7 @@ namespace pslang::ast
put_indent(out, options);
out << "condition\n";
if (block.condition)
child(self, block.condition);
child(block.condition);
else
{
put_indent(out, as_child(options));
@ -309,22 +295,20 @@ namespace pslang::ast
put_indent(out, options);
out << "body\n";
child(self, *block.statements);
child(*block.statements);
}
--options.indent_level;
}
template <typename Self>
void operator()(Self & self, while_block const & node)
void operator()(while_block const & node)
{
put_indent(out, options);
out << "while\n";
child(self, node.condition);
child(self, *node.statements);
child(node.condition);
child(*node.statements);
}
template <typename Self>
void operator()(Self & self, function_definition const & node)
void operator()(function_definition const & node)
{
put_indent(out, options);
out << "function { name = \"" << node.name << "\", return type = ";
@ -340,16 +324,15 @@ namespace pslang::ast
}
put_indent(out, options);
out << "body\n";
child(self, *node.statements);
child(*node.statements);
}
template <typename Self>
void operator()(Self & self, return_statement const & node)
void operator()(return_statement const & node)
{
put_indent(out, options);
out << "return\n";
if (node.value)
child(self, node.value);
child(node.value);
}
void operator()(field_definition const & node)
@ -360,13 +343,12 @@ namespace pslang::ast
out << " }\n";
}
template <typename Self>
void operator()(Self & self, struct_definition const & node)
void operator()(struct_definition const & node)
{
put_indent(out, options);
out << "struct { name = \"" << node.name << "\" }\n";
for (auto const & field : node.fields)
child(self, field);
child(field);
}
};

View file

@ -55,11 +55,6 @@ namespace pslang::ast
bool is_global_scope = false;
};
struct context
{
std::vector<scope> scopes;
};
struct resolve_identifiers_visitor
{
std::vector<scope> scopes;
@ -70,18 +65,16 @@ namespace pslang::ast
void operator()(types::primitive_type const &)
{}
template <typename Self>
void operator()(Self & self, array_type const & array_type)
void operator()(array_type const & array_type)
{
self(*array_type.element_type);
apply(*this, *array_type.element_type);
}
template <typename Self>
void operator()(Self & self, function_type const & function_type)
void operator()(function_type const & function_type)
{
for (auto const & argument : function_type.arguments)
self(*argument);
self(*function_type.result);
apply(*this, *argument);
apply(*this, *function_type.result);
}
void operator()(type_identifier & identifier)
@ -118,52 +111,45 @@ namespace pslang::ast
throw parse_error("Identifier \"" + identifier.name + "\" not found", identifier.location);
}
template <typename Self>
void operator()(Self & self, unary_operation const & unary_operation)
void operator()(unary_operation const & unary_operation)
{
self(*unary_operation.arg1);
apply(*this, *unary_operation.arg1);
}
template <typename Self>
void operator()(Self & self, binary_operation const & binary_operation)
void operator()(binary_operation const & binary_operation)
{
self(*binary_operation.arg1);
self(*binary_operation.arg2);
apply(*this, *binary_operation.arg1);
apply(*this, *binary_operation.arg2);
}
template <typename Self>
void operator()(Self & self, cast_operation const & cast_operation)
void operator()(cast_operation const & cast_operation)
{
self(*cast_operation.expression);
apply(*this, *cast_operation.expression);
apply(*this, *cast_operation.type);
}
template <typename Self>
void operator()(Self & self, function_call const & function_call)
void operator()(function_call const & function_call)
{
self(*function_call.function);
apply(*this, *function_call.function);
for (auto const & argument : function_call.arguments)
self(*argument);
apply(*this, *argument);
}
template <typename Self>
void operator()(Self & self, array const & array)
void operator()(array const & array)
{
for (auto const & element : array.elements)
self(*element);
apply(*this, *element);
}
template <typename Self>
void operator()(Self & self, array_access const & array_access)
void operator()(array_access const & array_access)
{
self(*array_access.array);
self(*array_access.index);
apply(*this, *array_access.array);
apply(*this, *array_access.index);
}
template <typename Self>
void operator()(Self & self, field_access const & field_access)
void operator()(field_access const & field_access)
{
self(*field_access.object);
apply(*this, *field_access.object);
}
void operator()(expression_ptr const & expression_ptr)
@ -171,11 +157,10 @@ namespace pslang::ast
apply(*this, *expression_ptr);
}
template <typename Self>
void operator()(Self & self, assignment const & assignment)
void operator()(assignment const & assignment)
{
self(assignment.lhs);
self(assignment.rhs);
ast::apply(*this, assignment.lhs);
ast::apply(*this, assignment.rhs);
}
void operator()(variable_declaration const & variable_declaration)
@ -205,30 +190,27 @@ namespace pslang::ast
throw invalid_ast_error("else blocks cannot be present in the final AST", else_block.location);
}
template <typename Self>
void operator()(Self & self, if_chain const & if_chain)
void operator()(if_chain const & if_chain)
{
for (auto const & block : if_chain.blocks)
{
if (block.condition)
apply(*this, *block.condition);
scopes.emplace_back();
self(*block.statements);
apply(*this, *block.statements);
scopes.pop_back();
}
}
template <typename Self>
void operator()(Self & self, while_block const & while_block)
void operator()(while_block const & while_block)
{
apply(*this, *while_block.condition);
scopes.emplace_back();
self(*while_block.statements);
apply(*this, *while_block.statements);
scopes.pop_back();
}
template <typename Self>
void operator()(Self & self, function_definition const & function_definition)
void operator()(function_definition const & function_definition)
{
if (scopes.back().contains(function_definition.name))
throw parse_error("Identifier \"" + function_definition.name + "\" is already defined at this scope", function_definition.location);
@ -249,7 +231,7 @@ namespace pslang::ast
auto & scope = scopes.emplace_back();
scope.is_function_scope = true;
scope.variables = std::move(argument_names);
self(*function_definition.statements);
apply(*this, *function_definition.statements);
scopes.pop_back();
}
@ -264,14 +246,13 @@ namespace pslang::ast
apply(*this, *field_definition.type);
}
template <typename Self>
void operator()(Self & self, struct_definition const & struct_definition)
void operator()(struct_definition const & struct_definition)
{
if (scopes.back().contains(struct_definition.name))
throw parse_error("Identifier \"" + struct_definition.name + "\" is already defined at this scope", struct_definition.location);
for (auto const & field : struct_definition.fields)
self(field);
apply(*this, field);
scopes.back().structs.insert(struct_definition.name);
}

View file

@ -16,14 +16,7 @@ namespace pslang::types
template <typename Type>
void operator()(Type const & type)
{
if constexpr (std::is_invocable_v<Visitor, const_visitor_helper &, Type const &>)
{
visitor(*this, type);
}
else
{
visitor(type);
}
visitor(type);
}
void operator()(types::primitive_type const & type)
@ -45,14 +38,7 @@ namespace pslang::types
template <typename Type>
void operator()(Type & type)
{
if constexpr (std::is_invocable_v<Visitor, visitor_helper &, Type &>)
{
visitor(*this, type);
}
else
{
visitor(type);
}
visitor(type);
}
void operator()(types::primitive_type & type)

View file

@ -71,21 +71,19 @@ namespace pslang::types
out << "f64";
}
template <typename Self>
void operator()(Self & self, array_type const & type)
void operator()(array_type const & type)
{
self(*type.element_type);
apply(*this, *type.element_type);
out << "[" << type.size << "]";
}
template <typename Self>
void operator()(Self & self, function_type const & type)
void operator()(function_type const & type)
{
if (type.arguments.size() == 1)
{
self(*type.arguments.front());
apply(*this, *type.arguments.front());
out << " -> ";
self(*type.result);
apply(*this, *type.result);
return;
}
@ -95,10 +93,10 @@ namespace pslang::types
{
if (!first) out << ", ";
first = false;
self(*argument);
apply(*this, *argument);
}
out << ") -> ";
self(*type.result);
apply(*this, *type.result);
}
void operator()(named_type const & type)