From 092ed1cc8ace0a8ac0cd9660d381c93e7fd81cc4 Mon Sep 17 00:00:00 2001 From: Dan Klishch Date: Fri, 18 Aug 2023 16:23:29 -0400 Subject: [PATCH] JSSpecCompiler: Allow storing `NullableTree`s in nodes And use this in ElseIfBranch node. --- .../CodeGenerators/JSSpecCompiler/AST/AST.cpp | 27 +++++++++++++++++-- .../CodeGenerators/JSSpecCompiler/AST/AST.h | 14 ++++++---- .../JSSpecCompiler/AST/ASTPrinting.cpp | 6 ++--- .../Compiler/GenericASTPass.cpp | 13 ++++++++- .../JSSpecCompiler/Compiler/GenericASTPass.h | 3 ++- .../JSSpecCompiler/Parser/TextParser.cpp | 9 +++---- .../JSSpecCompiler/Parser/TextParser.h | 2 +- 7 files changed, 56 insertions(+), 18 deletions(-) diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.cpp index 18e559dbb8..1d74b8a11a 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.cpp @@ -8,6 +8,29 @@ namespace JSSpecCompiler { +Tree NodeSubtreePointer::get(Badge) +{ + 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, NullableTree replacement) +{ + m_tree_ptr.visit( + [&](NullableTree* nullable_tree) { + *nullable_tree = replacement; + }, + [&](Tree* tree) { + *tree = replacement.release_nonnull(); + }); +} + Vector BinaryOperation::subtrees() { return { { &m_left }, { &m_right } }; @@ -43,8 +66,8 @@ Vector IfBranch::subtrees() Vector ElseIfBranch::subtrees() { - if (m_condition.has_value()) - return { { &m_condition.value() }, { &m_branch } }; + if (m_condition) + return { { &m_condition }, { &m_branch } }; return { { &m_branch } }; } diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.h b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.h index 30a6500dc0..b89cdfeb9c 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.h +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.h @@ -28,12 +28,16 @@ public: { } - Tree& get(Badge) { return *m_tree_ptr; } + NodeSubtreePointer(NullableTree* tree_ptr) + : m_tree_ptr(tree_ptr) + { + } - void replace_subtree(Badge, Tree tree) { *m_tree_ptr = move(tree); } + Tree get(Badge); + void replace_subtree(Badge, NullableTree replacement); private: - Tree* m_tree_ptr; + Variant m_tree_ptr; }; // ===== Generic nodes ===== @@ -258,7 +262,7 @@ protected: class ElseIfBranch : public Node { public: - ElseIfBranch(Optional condition, Tree branch) + ElseIfBranch(NullableTree condition, Tree branch) : m_condition(condition) , m_branch(branch) { @@ -266,7 +270,7 @@ public: Vector subtrees() override; - Optional m_condition; + NullableTree m_condition; Tree m_branch; protected: diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/ASTPrinting.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/ASTPrinting.cpp index a07fe99840..ae2beff796 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/ASTPrinting.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/ASTPrinting.cpp @@ -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); } diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/GenericASTPass.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/GenericASTPass.cpp index f37dd23a6b..23189e780f 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/GenericASTPass.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/GenericASTPass.cpp @@ -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)); } diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/GenericASTPass.h b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/GenericASTPass.h index 6d82fc3e94..8f00f91b79 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/GenericASTPass.h +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/GenericASTPass.h @@ -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); diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.cpp index c0452da8c1..d0dfd2e9e1 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.cpp @@ -382,7 +382,7 @@ ParseErrorOr TextParser::parse_if_beginning( auto rollback = rollback_point(); bool is_if_branch = !consume_word("if"sv).is_error(); - Optional condition; + NullableTree condition = nullptr; if (is_if_branch) { condition = TRY(parse_condition()); } else { @@ -406,9 +406,8 @@ ParseErrorOr TextParser::parse_inline_if_else() rollback.disarm(); if (is_if_branch) - return make_ref_counted(*condition, then_branch); - else - return make_ref_counted(condition, then_branch); + return make_ref_counted(condition.release_nonnull(), then_branch); + return make_ref_counted(condition, then_branch); } // :== then$ @@ -437,7 +436,7 @@ ParseErrorOr TextParser::parse_else(Tree else_branch) TRY(expect_eof()); rollback.disarm(); - return make_ref_counted(Optional {}, else_branch); + return make_ref_counted(nullptr, else_branch); } // | diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.h b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.h index 47e6b171ad..956e484cf6 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.h +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.h @@ -33,7 +33,7 @@ public: private: struct IfConditionParseResult { bool is_if_branch; - Optional condition; + NullableTree condition; }; void retreat();