IfBranchMergingPass.cpp 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. * Copyright (c) 2023, Dan Klishch <danilklishch@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/TypeCasts.h>
  7. #include "AST/AST.h"
  8. #include "Compiler/IfBranchMergingPass.h"
  9. namespace JSSpecCompiler {
  10. RecursionDecision IfBranchMergingPass::on_entry(Tree tree)
  11. {
  12. if (auto list = as<TreeList>(tree); list) {
  13. Vector<Tree> result;
  14. Vector<Tree> unmerged_branches;
  15. auto merge_if_needed = [&] {
  16. if (!unmerged_branches.is_empty()) {
  17. result.append(merge_branches(unmerged_branches));
  18. unmerged_branches.clear();
  19. }
  20. };
  21. for (auto const& node : list->m_expressions) {
  22. if (is<IfBranch>(node.ptr())) {
  23. merge_if_needed();
  24. unmerged_branches.append(node);
  25. } else if (is<ElseIfBranch>(node.ptr())) {
  26. unmerged_branches.append(node);
  27. } else {
  28. merge_if_needed();
  29. result.append(node);
  30. }
  31. }
  32. merge_if_needed();
  33. list->m_expressions = move(result);
  34. }
  35. return RecursionDecision::Recurse;
  36. }
  37. Tree IfBranchMergingPass::merge_branches(Vector<Tree> const& unmerged_branches)
  38. {
  39. static const Tree error = make_ref_counted<ErrorNode>("Cannot make sense of if-elseif-else chain"sv);
  40. VERIFY(unmerged_branches.size() >= 1);
  41. Vector<Tree> conditions;
  42. Vector<Tree> branches;
  43. NullableTree else_branch;
  44. if (auto if_branch = as<IfBranch>(unmerged_branches[0]); if_branch) {
  45. conditions.append(if_branch->m_condition);
  46. branches.append(if_branch->m_branch);
  47. } else {
  48. return error;
  49. }
  50. for (size_t i = 1; i < unmerged_branches.size(); ++i) {
  51. auto branch = as<ElseIfBranch>(unmerged_branches[i]);
  52. if (!branch)
  53. return error;
  54. if (!branch->m_condition) {
  55. // There might be situation like:
  56. // 1. If <condition>, then
  57. // ...
  58. // 2. Else,
  59. // a. If <condition>, then
  60. // ...
  61. // 3. Else,
  62. // ...
  63. auto substep_list = as<TreeList>(branch->m_branch);
  64. if (substep_list && substep_list->m_expressions.size() == 1) {
  65. if (auto nested_if = as<IfBranch>(substep_list->m_expressions[0]); nested_if)
  66. branch = make_ref_counted<ElseIfBranch>(nested_if->m_condition, nested_if->m_branch);
  67. }
  68. }
  69. if (branch->m_condition) {
  70. conditions.append(branch->m_condition.release_nonnull());
  71. branches.append(branch->m_branch);
  72. } else {
  73. if (i + 1 != unmerged_branches.size())
  74. return error;
  75. else_branch = branch->m_branch;
  76. }
  77. }
  78. return make_ref_counted<IfElseIfChain>(move(conditions), move(branches), else_branch);
  79. }
  80. }