mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 20:15:17 +00:00
JSSpecCompiler: Add infrastructure to run compiler passes on AST
This commit is contained in:
parent
cd8f4aaa7d
commit
198591cc20
Notes:
sideshowbarker
2024-07-17 11:29:41 +09:00
Author: https://github.com/DanShaders Commit: https://github.com/SerenityOS/serenity/commit/198591cc20 Pull-request: https://github.com/SerenityOS/serenity/pull/20876 Reviewed-by: https://github.com/ADKaster
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());
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
set(SOURCES
|
||||
AST/AST.cpp
|
||||
AST/ASTPrinting.cpp
|
||||
Compiler/GenericASTPass.cpp
|
||||
Parser/Lexer.cpp
|
||||
Parser/ParseError.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
Reference in a new issue