JSSpecCompiler: Add infrastructure to run compiler passes on AST

This commit is contained in:
Dan Klishch 2023-08-18 13:12:20 -04:00 committed by Andrew Kaster
parent cd8f4aaa7d
commit 198591cc20
Notes: sideshowbarker 2024-07-17 11:29:41 +09:00
6 changed files with 243 additions and 0 deletions

View file

@ -0,0 +1,77 @@
/*
* Copyright (c) 2023, Dan Klishch <danilklishch@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "AST/AST.h"
namespace JSSpecCompiler {
Vector<NodeSubtreePointer> BinaryOperation::subtrees()
{
return { { &m_left }, { &m_right } };
}
Vector<NodeSubtreePointer> UnaryOperation::subtrees()
{
return { { &m_operand } };
}
Vector<NodeSubtreePointer> IsOneOfOperation::subtrees()
{
Vector<NodeSubtreePointer> result = { { &m_operand } };
for (auto& child : m_compare_values)
result.append({ &child });
return result;
}
Vector<NodeSubtreePointer> ReturnExpression::subtrees()
{
return { { &m_return_value } };
}
Vector<NodeSubtreePointer> AssertExpression::subtrees()
{
return { { &m_condition } };
}
Vector<NodeSubtreePointer> IfBranch::subtrees()
{
return { { &m_condition }, { &m_branch } };
}
Vector<NodeSubtreePointer> ElseIfBranch::subtrees()
{
if (m_condition.has_value())
return { { &m_condition.value() }, { &m_branch } };
return { { &m_branch } };
}
Vector<NodeSubtreePointer> TreeList::subtrees()
{
Vector<NodeSubtreePointer> result;
for (auto& expression : m_expressions)
result.append({ &expression });
return result;
}
Vector<NodeSubtreePointer> RecordDirectListInitialization::subtrees()
{
Vector<NodeSubtreePointer> result { &m_type_reference };
for (auto& argument : m_arguments) {
result.append({ &argument.name });
result.append({ &argument.value });
}
return result;
}
Vector<NodeSubtreePointer> FunctionCall::subtrees()
{
Vector<NodeSubtreePointer> result = { { &m_name } };
for (auto& child : m_arguments)
result.append({ &child });
return result;
}
}

View file

@ -20,6 +20,21 @@ RefPtr<T> as(NullableTree const& tree)
return dynamic_cast<T*>(tree.ptr());
}
class NodeSubtreePointer {
public:
NodeSubtreePointer(Tree* tree_ptr)
: m_tree_ptr(tree_ptr)
{
}
Tree& get() { return *m_tree_ptr; }
void replace_subtree(Tree tree) { *m_tree_ptr = move(tree); }
private:
Tree* m_tree_ptr;
};
// ===== Generic nodes =====
class Node : public RefCounted<Node> {
public:
@ -27,6 +42,9 @@ public:
void format_tree(StringBuilder& builder);
// For expressions, order must be the same as the evaluation order.
virtual Vector<NodeSubtreePointer> subtrees() { return {}; }
virtual bool is_type() { return false; }
protected:
@ -128,6 +146,8 @@ public:
{
}
Vector<NodeSubtreePointer> subtrees() override;
BinaryOperator m_operation;
Tree m_left;
Tree m_right;
@ -144,6 +164,8 @@ public:
{
}
Vector<NodeSubtreePointer> subtrees() override;
UnaryOperator m_operation;
Tree m_operand;
@ -159,6 +181,8 @@ public:
{
}
Vector<NodeSubtreePointer> subtrees() override;
Tree m_operand;
Vector<Tree> m_compare_values;
@ -186,6 +210,8 @@ public:
{
}
Vector<NodeSubtreePointer> subtrees() override;
Tree m_return_value;
protected:
@ -199,6 +225,8 @@ public:
{
}
Vector<NodeSubtreePointer> subtrees() override;
Tree m_condition;
protected:
@ -213,6 +241,8 @@ public:
{
}
Vector<NodeSubtreePointer> subtrees() override;
Tree m_condition;
Tree m_branch;
@ -228,6 +258,8 @@ public:
{
}
Vector<NodeSubtreePointer> subtrees() override;
Optional<Tree> m_condition;
Tree m_branch;
@ -242,6 +274,8 @@ public:
{
}
Vector<NodeSubtreePointer> subtrees() override;
Vector<Tree> m_expressions;
protected:
@ -261,6 +295,8 @@ public:
{
}
Vector<NodeSubtreePointer> subtrees() override;
Tree m_type_reference;
Vector<Argument> m_arguments;
@ -276,6 +312,8 @@ public:
{
}
Vector<NodeSubtreePointer> subtrees() override;
Tree m_name;
Vector<Tree> m_arguments;

View file

@ -1,5 +1,7 @@
set(SOURCES
AST/AST.cpp
AST/ASTPrinting.cpp
Compiler/GenericASTPass.cpp
Parser/Lexer.cpp
Parser/ParseError.cpp
Parser/SpecParser.cpp

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2023, Dan Klishch <danilklishch@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/NonnullRefPtr.h>
#include <AK/RecursionDecision.h>
#include "Forward.h"
namespace JSSpecCompiler {
class CompilerPass {
public:
CompilerPass(FunctionRef function)
: m_function(function)
{
}
virtual ~CompilerPass() = default;
virtual void run() = 0;
protected:
FunctionRef m_function;
};
}

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2023, Dan Klishch <danilklishch@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "Compiler/GenericASTPass.h"
#include "AST/AST.h"
#include "Function.h"
namespace JSSpecCompiler {
void RecursiveASTVisitor::run_in_subtree(Tree& tree)
{
NodeSubtreePointer pointer { &tree };
recurse(tree, pointer);
}
void RecursiveASTVisitor::replace_current_node_with(Tree tree)
{
m_current_subtree_pointer->replace_subtree(move(tree));
}
RecursionDecision RecursiveASTVisitor::recurse(Tree root, NodeSubtreePointer& pointer)
{
RecursionDecision decision;
m_current_subtree_pointer = &pointer;
decision = on_entry(root);
if (decision == RecursionDecision::Recurse) {
for (auto& child : root->subtrees()) {
if (recurse(child.get(), child) == RecursionDecision::Break)
return RecursionDecision::Break;
}
}
m_current_subtree_pointer = &pointer;
on_leave(root);
return RecursionDecision::Continue;
}
void GenericASTPass::run()
{
run_in_subtree(m_function->m_ast);
}
}

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2023, Dan Klishch <danilklishch@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/NonnullRefPtr.h>
#include <AK/RecursionDecision.h>
#include "Compiler/CompilerPass.h"
namespace JSSpecCompiler {
class RecursiveASTVisitor {
public:
virtual ~RecursiveASTVisitor() = default;
void run_in_subtree(Tree& tree);
protected:
virtual RecursionDecision on_entry(Tree) { return RecursionDecision::Recurse; }
virtual void on_leave(Tree) { }
void replace_current_node_with(Tree tree);
private:
RecursionDecision recurse(Tree root, NodeSubtreePointer& pointer);
NodeSubtreePointer* m_current_subtree_pointer = nullptr;
};
class GenericASTPass
: public CompilerPass
, protected RecursiveASTVisitor {
public:
GenericASTPass(FunctionRef function)
: CompilerPass(function)
{
}
void run() override;
};
}