statement.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "explorer/ast/statement.h"
  5. #include "common/check.h"
  6. #include "explorer/ast/declaration.h"
  7. #include "explorer/base/arena.h"
  8. #include "llvm/Support/Casting.h"
  9. namespace Carbon {
  10. using llvm::cast;
  11. Statement::~Statement() = default;
  12. void Statement::PrintID(llvm::raw_ostream& out) const {
  13. switch (kind()) {
  14. case StatementKind::Match:
  15. out << "match (...) { ... }";
  16. break;
  17. case StatementKind::While:
  18. out << "while (...) { ... }";
  19. break;
  20. case StatementKind::For:
  21. out << "for (...) { ... }";
  22. break;
  23. case StatementKind::Break:
  24. out << "break;";
  25. break;
  26. case StatementKind::Continue:
  27. out << "continue;";
  28. break;
  29. case StatementKind::VariableDefinition: {
  30. const auto& var = cast<VariableDefinition>(*this);
  31. if (var.is_returned()) {
  32. out << "returned ";
  33. }
  34. out << "var ...";
  35. if (var.has_init()) {
  36. out << " = ...";
  37. }
  38. out << ";";
  39. break;
  40. }
  41. case StatementKind::ExpressionStatement:
  42. out << "<expression>;";
  43. break;
  44. case StatementKind::Assign: {
  45. const auto& assign = cast<Assign>(*this);
  46. out << "... " << AssignOperatorToString(assign.op()) << " ...;";
  47. break;
  48. }
  49. case StatementKind::IncrementDecrement: {
  50. const auto& inc_dec = cast<IncrementDecrement>(*this);
  51. out << (inc_dec.is_increment() ? "++" : "--") << "...;";
  52. break;
  53. }
  54. case StatementKind::If: {
  55. const auto& if_stmt = cast<If>(*this);
  56. out << "if (...) { ... }";
  57. if (if_stmt.else_block()) {
  58. out << " else { ... }";
  59. }
  60. break;
  61. }
  62. case StatementKind::ReturnVar:
  63. out << "return var;";
  64. break;
  65. case StatementKind::ReturnExpression: {
  66. const auto& ret = cast<ReturnExpression>(*this);
  67. if (ret.is_omitted_expression()) {
  68. out << "return;";
  69. } else {
  70. out << "return ...;";
  71. }
  72. break;
  73. }
  74. case StatementKind::Block:
  75. out << "{ ... }";
  76. break;
  77. }
  78. }
  79. void Statement::PrintIndent(int indent_num_spaces,
  80. llvm::raw_ostream& out) const {
  81. out.indent(indent_num_spaces);
  82. switch (kind()) {
  83. case StatementKind::Match: {
  84. const auto& match = cast<Match>(*this);
  85. out << "match (" << match.expression() << ") {\n";
  86. for (const auto& clause : match.clauses()) {
  87. out.indent(indent_num_spaces + 2)
  88. << "case " << clause.pattern() << " =>\n";
  89. clause.statement().PrintIndent(indent_num_spaces + 2, out);
  90. out << "\n";
  91. }
  92. out.indent(indent_num_spaces) << "}";
  93. break;
  94. }
  95. case StatementKind::While: {
  96. const auto& while_stmt = cast<While>(*this);
  97. out << "while (" << while_stmt.condition() << ")\n";
  98. while_stmt.body().PrintIndent(indent_num_spaces, out);
  99. break;
  100. }
  101. case StatementKind::For: {
  102. const auto& for_stmt = cast<For>(*this);
  103. out << "for (" << for_stmt.variable_declaration() << " in "
  104. << for_stmt.loop_target() << ")\n";
  105. for_stmt.body().PrintIndent(indent_num_spaces, out);
  106. break;
  107. }
  108. case StatementKind::Break:
  109. out << "break;";
  110. break;
  111. case StatementKind::Continue:
  112. out << "continue;";
  113. break;
  114. case StatementKind::VariableDefinition: {
  115. const auto& var = cast<VariableDefinition>(*this);
  116. if (var.is_returned()) {
  117. out << "returned ";
  118. }
  119. out << "var " << var.pattern();
  120. if (var.has_init()) {
  121. out << " = " << var.init();
  122. }
  123. out << ";";
  124. break;
  125. }
  126. case StatementKind::ExpressionStatement:
  127. out << cast<ExpressionStatement>(*this).expression() << ";";
  128. break;
  129. case StatementKind::Assign: {
  130. const auto& assign = cast<Assign>(*this);
  131. out << assign.lhs() << " " << AssignOperatorToString(assign.op()) << " "
  132. << assign.rhs() << ";";
  133. break;
  134. }
  135. case StatementKind::IncrementDecrement: {
  136. const auto& inc_dec = cast<IncrementDecrement>(*this);
  137. out << (inc_dec.is_increment() ? "++" : "--") << inc_dec.argument()
  138. << ";";
  139. break;
  140. }
  141. case StatementKind::If: {
  142. const auto& if_stmt = cast<If>(*this);
  143. out << "if (" << if_stmt.condition() << ")\n";
  144. if_stmt.then_block().PrintIndent(indent_num_spaces, out);
  145. if (if_stmt.else_block()) {
  146. out << "\n";
  147. out.indent(indent_num_spaces) << "else\n";
  148. (*if_stmt.else_block())->PrintIndent(indent_num_spaces, out);
  149. }
  150. break;
  151. }
  152. case StatementKind::ReturnVar: {
  153. out << "return var;";
  154. break;
  155. }
  156. case StatementKind::ReturnExpression: {
  157. const auto& ret = cast<ReturnExpression>(*this);
  158. if (ret.is_omitted_expression()) {
  159. out << "return;";
  160. } else {
  161. out << "return " << ret.expression() << ";";
  162. }
  163. break;
  164. }
  165. case StatementKind::Block: {
  166. const auto& block = cast<Block>(*this);
  167. const auto statements = block.statements();
  168. out << "{\n";
  169. for (const auto* statement : statements) {
  170. statement->PrintIndent(indent_num_spaces + 2, out);
  171. out << "\n";
  172. }
  173. out.indent(indent_num_spaces) << "}";
  174. break;
  175. }
  176. }
  177. }
  178. auto AssignOperatorToString(AssignOperator op) -> std::string_view {
  179. switch (op) {
  180. case AssignOperator::Plain:
  181. return "=";
  182. case AssignOperator::Add:
  183. return "+=";
  184. case AssignOperator::Div:
  185. return "/=";
  186. case AssignOperator::Mul:
  187. return "*=";
  188. case AssignOperator::Mod:
  189. return "%=";
  190. case AssignOperator::Sub:
  191. return "-=";
  192. case AssignOperator::And:
  193. return "&=";
  194. case AssignOperator::Or:
  195. return "|=";
  196. case AssignOperator::Xor:
  197. return "^=";
  198. case AssignOperator::ShiftLeft:
  199. return "<<=";
  200. case AssignOperator::ShiftRight:
  201. return ">>=";
  202. }
  203. }
  204. Return::Return(CloneContext& context, const Return& other)
  205. : Statement(context, other), function_(context.Remap(other.function_)) {}
  206. } // namespace Carbon