mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 20:37:35 +00:00
JSSpecCompiler: Add infrastructure to run compiler passes on AST
This commit is contained in:
parent
cd8f4aaa7d
commit
198591cc20
6 changed files with 243 additions and 0 deletions
77
Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.cpp
Normal file
77
Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -20,6 +20,21 @@ RefPtr<T> as(NullableTree const& tree)
|
||||||
return dynamic_cast<T*>(tree.ptr());
|
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 =====
|
// ===== Generic nodes =====
|
||||||
class Node : public RefCounted<Node> {
|
class Node : public RefCounted<Node> {
|
||||||
public:
|
public:
|
||||||
|
@ -27,6 +42,9 @@ public:
|
||||||
|
|
||||||
void format_tree(StringBuilder& builder);
|
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; }
|
virtual bool is_type() { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -128,6 +146,8 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector<NodeSubtreePointer> subtrees() override;
|
||||||
|
|
||||||
BinaryOperator m_operation;
|
BinaryOperator m_operation;
|
||||||
Tree m_left;
|
Tree m_left;
|
||||||
Tree m_right;
|
Tree m_right;
|
||||||
|
@ -144,6 +164,8 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector<NodeSubtreePointer> subtrees() override;
|
||||||
|
|
||||||
UnaryOperator m_operation;
|
UnaryOperator m_operation;
|
||||||
Tree m_operand;
|
Tree m_operand;
|
||||||
|
|
||||||
|
@ -159,6 +181,8 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector<NodeSubtreePointer> subtrees() override;
|
||||||
|
|
||||||
Tree m_operand;
|
Tree m_operand;
|
||||||
Vector<Tree> m_compare_values;
|
Vector<Tree> m_compare_values;
|
||||||
|
|
||||||
|
@ -186,6 +210,8 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector<NodeSubtreePointer> subtrees() override;
|
||||||
|
|
||||||
Tree m_return_value;
|
Tree m_return_value;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -199,6 +225,8 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector<NodeSubtreePointer> subtrees() override;
|
||||||
|
|
||||||
Tree m_condition;
|
Tree m_condition;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -213,6 +241,8 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector<NodeSubtreePointer> subtrees() override;
|
||||||
|
|
||||||
Tree m_condition;
|
Tree m_condition;
|
||||||
Tree m_branch;
|
Tree m_branch;
|
||||||
|
|
||||||
|
@ -228,6 +258,8 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector<NodeSubtreePointer> subtrees() override;
|
||||||
|
|
||||||
Optional<Tree> m_condition;
|
Optional<Tree> m_condition;
|
||||||
Tree m_branch;
|
Tree m_branch;
|
||||||
|
|
||||||
|
@ -242,6 +274,8 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector<NodeSubtreePointer> subtrees() override;
|
||||||
|
|
||||||
Vector<Tree> m_expressions;
|
Vector<Tree> m_expressions;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -261,6 +295,8 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector<NodeSubtreePointer> subtrees() override;
|
||||||
|
|
||||||
Tree m_type_reference;
|
Tree m_type_reference;
|
||||||
Vector<Argument> m_arguments;
|
Vector<Argument> m_arguments;
|
||||||
|
|
||||||
|
@ -276,6 +312,8 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector<NodeSubtreePointer> subtrees() override;
|
||||||
|
|
||||||
Tree m_name;
|
Tree m_name;
|
||||||
Vector<Tree> m_arguments;
|
Vector<Tree> m_arguments;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
|
AST/AST.cpp
|
||||||
AST/ASTPrinting.cpp
|
AST/ASTPrinting.cpp
|
||||||
|
Compiler/GenericASTPass.cpp
|
||||||
Parser/Lexer.cpp
|
Parser/Lexer.cpp
|
||||||
Parser/ParseError.cpp
|
Parser/ParseError.cpp
|
||||||
Parser/SpecParser.cpp
|
Parser/SpecParser.cpp
|
||||||
|
|
|
@ -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;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue