JSSpecCompiler: Allow storing NullableTrees in nodes

And use this in ElseIfBranch node.
This commit is contained in:
Dan Klishch 2023-08-18 16:23:29 -04:00 committed by Andrew Kaster
parent 4eede5282c
commit 092ed1cc8a
Notes: sideshowbarker 2024-07-16 20:08:14 +09:00
7 changed files with 56 additions and 18 deletions

View file

@ -8,6 +8,29 @@
namespace JSSpecCompiler {
Tree NodeSubtreePointer::get(Badge<RecursiveASTVisitor>)
{
return m_tree_ptr.visit(
[&](NullableTree* nullable_tree) -> Tree {
NullableTree copy = *nullable_tree;
return copy.release_nonnull();
},
[&](Tree* tree) -> Tree {
return *tree;
});
}
void NodeSubtreePointer::replace_subtree(Badge<RecursiveASTVisitor>, NullableTree replacement)
{
m_tree_ptr.visit(
[&](NullableTree* nullable_tree) {
*nullable_tree = replacement;
},
[&](Tree* tree) {
*tree = replacement.release_nonnull();
});
}
Vector<NodeSubtreePointer> BinaryOperation::subtrees()
{
return { { &m_left }, { &m_right } };
@ -43,8 +66,8 @@ Vector<NodeSubtreePointer> IfBranch::subtrees()
Vector<NodeSubtreePointer> ElseIfBranch::subtrees()
{
if (m_condition.has_value())
return { { &m_condition.value() }, { &m_branch } };
if (m_condition)
return { { &m_condition }, { &m_branch } };
return { { &m_branch } };
}

View file

@ -28,12 +28,16 @@ public:
{
}
Tree& get(Badge<RecursiveASTVisitor>) { return *m_tree_ptr; }
NodeSubtreePointer(NullableTree* tree_ptr)
: m_tree_ptr(tree_ptr)
{
}
void replace_subtree(Badge<RecursiveASTVisitor>, Tree tree) { *m_tree_ptr = move(tree); }
Tree get(Badge<RecursiveASTVisitor>);
void replace_subtree(Badge<RecursiveASTVisitor>, NullableTree replacement);
private:
Tree* m_tree_ptr;
Variant<Tree*, NullableTree*> m_tree_ptr;
};
// ===== Generic nodes =====
@ -258,7 +262,7 @@ protected:
class ElseIfBranch : public Node {
public:
ElseIfBranch(Optional<Tree> condition, Tree branch)
ElseIfBranch(NullableTree condition, Tree branch)
: m_condition(condition)
, m_branch(branch)
{
@ -266,7 +270,7 @@ public:
Vector<NodeSubtreePointer> subtrees() override;
Optional<Tree> m_condition;
NullableTree m_condition;
Tree m_branch;
protected:

View file

@ -91,9 +91,9 @@ void IfBranch::dump_tree(StringBuilder& builder)
void ElseIfBranch::dump_tree(StringBuilder& builder)
{
dump_node(builder, "ElseIfBranch {}", m_condition.has_value() ? "ElseIf" : "Else");
if (m_condition.has_value())
(*m_condition)->format_tree(builder);
dump_node(builder, "ElseIfBranch {}", m_condition ? "ElseIf" : "Else");
if (m_condition)
m_condition->format_tree(builder);
m_branch->format_tree(builder);
}

View file

@ -10,13 +10,24 @@
namespace JSSpecCompiler {
void RecursiveASTVisitor::run_in_const_subtree(NullableTree nullable_tree)
{
if (nullable_tree) {
auto tree = nullable_tree.release_nonnull();
auto tree_copy = tree;
NodeSubtreePointer pointer { &tree };
recurse(tree, pointer);
VERIFY(tree == tree_copy);
}
}
void RecursiveASTVisitor::run_in_subtree(Tree& tree)
{
NodeSubtreePointer pointer { &tree };
recurse(tree, pointer);
}
void RecursiveASTVisitor::replace_current_node_with(Tree tree)
void RecursiveASTVisitor::replace_current_node_with(NullableTree tree)
{
m_current_subtree_pointer->replace_subtree({}, move(tree));
}

View file

@ -17,13 +17,14 @@ class RecursiveASTVisitor {
public:
virtual ~RecursiveASTVisitor() = default;
void run_in_const_subtree(NullableTree tree);
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);
void replace_current_node_with(NullableTree tree);
private:
RecursionDecision recurse(Tree root, NodeSubtreePointer& pointer);

View file

@ -382,7 +382,7 @@ ParseErrorOr<TextParser::IfConditionParseResult> TextParser::parse_if_beginning(
auto rollback = rollback_point();
bool is_if_branch = !consume_word("if"sv).is_error();
Optional<Tree> condition;
NullableTree condition = nullptr;
if (is_if_branch) {
condition = TRY(parse_condition());
} else {
@ -406,9 +406,8 @@ ParseErrorOr<Tree> TextParser::parse_inline_if_else()
rollback.disarm();
if (is_if_branch)
return make_ref_counted<IfBranch>(*condition, then_branch);
else
return make_ref_counted<ElseIfBranch>(condition, then_branch);
return make_ref_counted<IfBranch>(condition.release_nonnull(), then_branch);
return make_ref_counted<ElseIfBranch>(condition, then_branch);
}
// <if> :== <if_condition> then$ <substeps>
@ -437,7 +436,7 @@ ParseErrorOr<Tree> TextParser::parse_else(Tree else_branch)
TRY(expect_eof());
rollback.disarm();
return make_ref_counted<ElseIfBranch>(Optional<Tree> {}, else_branch);
return make_ref_counted<ElseIfBranch>(nullptr, else_branch);
}
// <simple_step> | <inline_if>

View file

@ -33,7 +33,7 @@ public:
private:
struct IfConditionParseResult {
bool is_if_branch;
Optional<Tree> condition;
NullableTree condition;
};
void retreat();