CppASTConverter.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. * Copyright (c) 2023, Dan Klishch <danilklishch@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "Parser/CppASTConverter.h"
  7. #include "Function.h"
  8. #include "Parser/SpecParser.h"
  9. namespace JSSpecCompiler {
  10. NonnullRefPtr<FunctionDefinition> CppASTConverter::convert()
  11. {
  12. StringView name = m_function->name()->full_name();
  13. Vector<Tree> toplevel_statements;
  14. for (auto const& statement : m_function->definition()->statements()) {
  15. auto maybe_tree = as_nullable_tree(statement);
  16. if (maybe_tree)
  17. toplevel_statements.append(maybe_tree.release_nonnull());
  18. }
  19. auto tree = make_ref_counted<TreeList>(move(toplevel_statements));
  20. return make_ref_counted<FunctionDefinition>(name, tree);
  21. }
  22. template<>
  23. NullableTree CppASTConverter::convert_node(Cpp::VariableDeclaration const& variable_declaration)
  24. {
  25. static Tree variable_declaration_present_error
  26. = make_ref_counted<ErrorNode>("Encountered variable declaration with initial value"sv);
  27. if (variable_declaration.initial_value() != nullptr)
  28. return variable_declaration_present_error;
  29. return nullptr;
  30. }
  31. template<>
  32. NullableTree CppASTConverter::convert_node(Cpp::ReturnStatement const& return_statement)
  33. {
  34. return make_ref_counted<ReturnNode>(as_tree(return_statement.value()));
  35. }
  36. template<>
  37. NullableTree CppASTConverter::convert_node(Cpp::FunctionCall const& function_call)
  38. {
  39. Vector<Tree> arguments;
  40. for (auto const& argument : function_call.arguments())
  41. arguments.append(as_tree(argument));
  42. return make_ref_counted<FunctionCall>(as_tree(function_call.callee()), move(arguments));
  43. }
  44. template<>
  45. NullableTree CppASTConverter::convert_node(Cpp::Name const& name)
  46. {
  47. return make_ref_counted<UnresolvedReference>(name.full_name());
  48. }
  49. template<>
  50. NullableTree CppASTConverter::convert_node(Cpp::IfStatement const& if_statement)
  51. {
  52. // NOTE: This is so complicated since we probably want to test IfBranchMergingPass, which
  53. // expects standalone `IfBranch` and `ElseIfBranch` nodes.
  54. Vector<Tree> trees;
  55. Cpp::IfStatement const* current = &if_statement;
  56. while (true) {
  57. auto predicate = as_tree(current->predicate());
  58. auto then_branch = as_possibly_empty_tree(current->then_statement());
  59. if (trees.is_empty())
  60. trees.append(make_ref_counted<IfBranch>(predicate, then_branch));
  61. else
  62. trees.append(make_ref_counted<ElseIfBranch>(predicate, then_branch));
  63. auto else_statement = dynamic_cast<Cpp::IfStatement const*>(current->else_statement());
  64. if (else_statement)
  65. current = else_statement;
  66. else
  67. break;
  68. }
  69. auto else_statement = current->else_statement();
  70. if (else_statement)
  71. trees.append(make_ref_counted<ElseIfBranch>(
  72. nullptr, as_possibly_empty_tree(else_statement)));
  73. return make_ref_counted<TreeList>(move(trees));
  74. }
  75. template<>
  76. NullableTree CppASTConverter::convert_node(Cpp::BlockStatement const& block)
  77. {
  78. Vector<Tree> statements;
  79. for (auto const& statement : block.statements()) {
  80. auto maybe_tree = as_nullable_tree(statement);
  81. if (maybe_tree)
  82. statements.append(maybe_tree.release_nonnull());
  83. }
  84. return make_ref_counted<TreeList>(move(statements));
  85. }
  86. template<>
  87. NullableTree CppASTConverter::convert_node(Cpp::AssignmentExpression const& assignment)
  88. {
  89. // NOTE: Later stages of the compilation process basically treat `BinaryOperator::Declaration`
  90. // the same as `BinaryOperator::Assignment`, so variable shadowing is impossible. The only
  91. // difference in their semantics is that "declarations" define names of local variables.
  92. // Since we are effectively ignoring actual C++ variable declarations, we need to define
  93. // locals somewhere else. Using "declarations" instead of "assignments" here does this job
  94. // cleanly.
  95. return make_ref_counted<BinaryOperation>(
  96. BinaryOperator::Declaration, as_tree(assignment.lhs()), as_tree(assignment.rhs()));
  97. }
  98. template<>
  99. NullableTree CppASTConverter::convert_node(Cpp::NumericLiteral const& literal)
  100. {
  101. // TODO: Numerical literals are not limited to i64.
  102. return make_ref_counted<MathematicalConstant>(literal.value().to_int<i64>().value());
  103. }
  104. NullableTree CppASTConverter::as_nullable_tree(Cpp::Statement const* statement)
  105. {
  106. static Tree unknown_ast_node_error
  107. = make_ref_counted<ErrorNode>("Encountered unknown C++ AST node"sv);
  108. Optional<NullableTree> result;
  109. auto dispatch_convert_if_one_of = [&]<typename... Ts> {
  110. (([&]<typename T> {
  111. if (result.has_value())
  112. return;
  113. auto casted_ptr = dynamic_cast<T const*>(statement);
  114. if (casted_ptr != nullptr)
  115. result = convert_node<T>(*casted_ptr);
  116. }).template operator()<Ts>(),
  117. ...);
  118. };
  119. dispatch_convert_if_one_of.operator()<
  120. Cpp::VariableDeclaration,
  121. Cpp::ReturnStatement,
  122. Cpp::FunctionCall,
  123. Cpp::Name,
  124. Cpp::IfStatement,
  125. Cpp::BlockStatement,
  126. Cpp::AssignmentExpression,
  127. Cpp::NumericLiteral>();
  128. if (result.has_value())
  129. return *result;
  130. return unknown_ast_node_error;
  131. }
  132. Tree CppASTConverter::as_tree(Cpp::Statement const* statement)
  133. {
  134. static Tree empty_tree_error
  135. = make_ref_counted<ErrorNode>("AST conversion unexpectedly produced empty tree"sv);
  136. auto result = as_nullable_tree(statement);
  137. if (result)
  138. return result.release_nonnull();
  139. return empty_tree_error;
  140. }
  141. Tree CppASTConverter::as_possibly_empty_tree(Cpp::Statement const* statement)
  142. {
  143. auto result = as_nullable_tree(statement);
  144. if (result)
  145. return result.release_nonnull();
  146. return make_ref_counted<TreeList>(Vector<Tree> {});
  147. }
  148. }