semantics_ir_factory.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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 "toolchain/semantics/semantics_ir_factory.h"
  5. #include <stack>
  6. #include "common/check.h"
  7. #include "llvm/ADT/StringMap.h"
  8. #include "llvm/Support/FormatVariadic.h"
  9. #include "toolchain/lexer/tokenized_buffer.h"
  10. #include "toolchain/parser/parse_node_kind.h"
  11. #include "toolchain/semantics/meta_node_block.h"
  12. #include "toolchain/semantics/nodes/expression_statement.h"
  13. #include "toolchain/semantics/parse_subtree_consumer.h"
  14. namespace Carbon {
  15. // The ParseTree is walked in reverse post order, meaning a lot of nodes are
  16. // added in reverse. This fixes that ordering to be the easier to understand
  17. // code ordering.
  18. template <typename T>
  19. static void FixReverseOrdering(T& container) {
  20. std::reverse(container.begin(), container.end());
  21. }
  22. auto SemanticsIRFactory::Build(const ParseTree& parse_tree) -> SemanticsIR {
  23. SemanticsIRFactory builder(parse_tree);
  24. builder.Build();
  25. return builder.semantics_;
  26. }
  27. void SemanticsIRFactory::Build() {
  28. auto subtree = ParseSubtreeConsumer::ForTree(parse_tree());
  29. // FileEnd is a placeholder node which can be discarded.
  30. RequireNodeEmpty(subtree.RequireConsume(ParseNodeKind::FileEnd()));
  31. llvm::SmallVector<Semantics::Declaration, 0> nodes;
  32. llvm::StringMap<Semantics::Declaration> name_lookup;
  33. while (llvm::Optional<ParseTree::Node> node = subtree.TryConsume()) {
  34. switch (auto node_kind = parse_tree().node_kind(*node)) {
  35. case ParseNodeKind::FunctionDeclaration(): {
  36. auto [name, decl] = TransformFunctionDeclaration(*node);
  37. nodes.push_back(decl);
  38. name_lookup[name] = decl;
  39. break;
  40. }
  41. default:
  42. CARBON_FATAL() << "At index " << node->index() << ", unexpected "
  43. << node_kind;
  44. }
  45. }
  46. FixReverseOrdering(nodes);
  47. semantics_.root_block_ =
  48. Semantics::DeclarationBlock(std::move(nodes), std::move(name_lookup));
  49. }
  50. void SemanticsIRFactory::RequireNodeEmpty(ParseTree::Node node) {
  51. auto subtree_size = parse_tree().node_subtree_size(node);
  52. CARBON_CHECK(subtree_size == 1)
  53. << "At index " << node.index() << ", expected "
  54. << parse_tree().node_kind(node)
  55. << "would have subtree_size of 1, but was " << subtree_size;
  56. }
  57. auto SemanticsIRFactory::TransformCodeBlock(ParseTree::Node node)
  58. -> Semantics::StatementBlock {
  59. CARBON_CHECK(parse_tree().node_kind(node) == ParseNodeKind::CodeBlock());
  60. auto subtree = ParseSubtreeConsumer::ForParent(parse_tree(), node);
  61. RequireNodeEmpty(subtree.RequireConsume(ParseNodeKind::CodeBlockEnd()));
  62. llvm::SmallVector<Semantics::Statement, 0> nodes;
  63. while (llvm::Optional<ParseTree::Node> child = subtree.TryConsume()) {
  64. switch (auto child_kind = parse_tree().node_kind(*child)) {
  65. case ParseNodeKind::ExpressionStatement():
  66. nodes.push_back(TransformExpressionStatement(*child));
  67. break;
  68. case ParseNodeKind::ReturnStatement():
  69. nodes.push_back(TransformReturnStatement(*child));
  70. break;
  71. case ParseNodeKind::VariableDeclaration():
  72. // TODO: Handle.
  73. break;
  74. default:
  75. CARBON_FATAL() << "At index " << child->index() << ", unexpected "
  76. << child_kind;
  77. }
  78. }
  79. FixReverseOrdering(nodes);
  80. return Semantics::StatementBlock(std::move(nodes),
  81. /*name_lookup=*/{});
  82. }
  83. auto SemanticsIRFactory::TransformDeclaredName(ParseTree::Node node)
  84. -> Semantics::DeclaredName {
  85. CARBON_CHECK(parse_tree().node_kind(node) == ParseNodeKind::DeclaredName());
  86. RequireNodeEmpty(node);
  87. return Semantics::DeclaredName(node);
  88. }
  89. auto SemanticsIRFactory::TransformExpression(ParseTree::Node node)
  90. -> Semantics::Expression {
  91. switch (auto node_kind = parse_tree().node_kind(node)) {
  92. case ParseNodeKind::Literal():
  93. RequireNodeEmpty(node);
  94. return semantics_.expressions_.Store(Semantics::Literal(node));
  95. case ParseNodeKind::InfixOperator():
  96. return semantics_.expressions_.Store(TransformInfixOperator(node));
  97. default:
  98. CARBON_FATAL() << "At index " << node.index() << ", unexpected "
  99. << node_kind;
  100. break;
  101. }
  102. }
  103. auto SemanticsIRFactory::TransformExpressionStatement(ParseTree::Node node)
  104. -> Semantics::Statement {
  105. CARBON_CHECK(parse_tree().node_kind(node) ==
  106. ParseNodeKind::ExpressionStatement());
  107. auto subtree = ParseSubtreeConsumer::ForParent(parse_tree(), node);
  108. RequireNodeEmpty(subtree.RequireConsume(ParseNodeKind::StatementEnd()));
  109. return semantics_.statements_.Store(Semantics::ExpressionStatement(
  110. TransformExpression(subtree.RequireConsume())));
  111. }
  112. auto SemanticsIRFactory::TransformFunctionDeclaration(ParseTree::Node node)
  113. -> std::tuple<llvm::StringRef, Semantics::Declaration> {
  114. CARBON_CHECK(parse_tree().node_kind(node) ==
  115. ParseNodeKind::FunctionDeclaration());
  116. auto subtree = ParseSubtreeConsumer::ForParent(parse_tree(), node);
  117. auto body =
  118. TransformCodeBlock(subtree.RequireConsume(ParseNodeKind::CodeBlock()));
  119. llvm::Optional<Semantics::Expression> return_type_expr;
  120. if (auto return_type_node = subtree.TryConsume(ParseNodeKind::ReturnType())) {
  121. return_type_expr = TransformReturnType(*return_type_node);
  122. }
  123. auto params = TransformParameterList(
  124. subtree.RequireConsume(ParseNodeKind::ParameterList()));
  125. auto name = TransformDeclaredName(
  126. subtree.RequireConsume(ParseNodeKind::DeclaredName()));
  127. auto decl = semantics_.declarations_.Store(
  128. Semantics::Function(node, name, params, return_type_expr, body));
  129. return std::make_tuple(parse_tree().GetNodeText(name.node()), decl);
  130. }
  131. auto SemanticsIRFactory::TransformInfixOperator(ParseTree::Node node)
  132. -> Semantics::InfixOperator {
  133. CARBON_CHECK(parse_tree().node_kind(node) == ParseNodeKind::InfixOperator());
  134. auto subtree = ParseSubtreeConsumer::ForParent(parse_tree(), node);
  135. auto rhs = TransformExpression(subtree.RequireConsume());
  136. auto lhs = TransformExpression(subtree.RequireConsume());
  137. return Semantics::InfixOperator(node, lhs, rhs);
  138. }
  139. auto SemanticsIRFactory::TransformParameterList(ParseTree::Node node)
  140. -> llvm::SmallVector<Semantics::PatternBinding, 0> {
  141. CARBON_CHECK(parse_tree().node_kind(node) == ParseNodeKind::ParameterList());
  142. auto subtree = ParseSubtreeConsumer::ForParent(parse_tree(), node);
  143. RequireNodeEmpty(subtree.RequireConsume(ParseNodeKind::ParameterListEnd()));
  144. llvm::SmallVector<Semantics::PatternBinding, 0> params;
  145. if (auto first_param_node =
  146. subtree.TryConsume(ParseNodeKind::PatternBinding())) {
  147. params.push_back(TransformPatternBinding(*first_param_node));
  148. while (auto comma_node =
  149. subtree.TryConsume(ParseNodeKind::ParameterListComma())) {
  150. RequireNodeEmpty(*comma_node);
  151. params.push_back(TransformPatternBinding(
  152. subtree.RequireConsume(ParseNodeKind::PatternBinding())));
  153. }
  154. }
  155. FixReverseOrdering(params);
  156. return params;
  157. }
  158. auto SemanticsIRFactory::TransformPatternBinding(ParseTree::Node node)
  159. -> Semantics::PatternBinding {
  160. CARBON_CHECK(parse_tree().node_kind(node) == ParseNodeKind::PatternBinding());
  161. auto subtree = ParseSubtreeConsumer::ForParent(parse_tree(), node);
  162. auto type = TransformExpression(subtree.RequireConsume());
  163. auto name = TransformDeclaredName(
  164. subtree.RequireConsume(ParseNodeKind::DeclaredName()));
  165. return Semantics::PatternBinding(node, name, type);
  166. }
  167. auto SemanticsIRFactory::TransformReturnStatement(ParseTree::Node node)
  168. -> Semantics::Statement {
  169. CARBON_CHECK(parse_tree().node_kind(node) ==
  170. ParseNodeKind::ReturnStatement());
  171. auto subtree = ParseSubtreeConsumer::ForParent(parse_tree(), node);
  172. RequireNodeEmpty(subtree.RequireConsume(ParseNodeKind::StatementEnd()));
  173. auto expr = subtree.TryConsume();
  174. if (expr) {
  175. // return expr;
  176. return semantics_.statements_.Store(
  177. Semantics::Return(node, TransformExpression(*expr)));
  178. } else {
  179. // return;
  180. return semantics_.statements_.Store(Semantics::Return(node, llvm::None));
  181. }
  182. }
  183. auto SemanticsIRFactory::TransformReturnType(ParseTree::Node node)
  184. -> Semantics::Expression {
  185. CARBON_CHECK(parse_tree().node_kind(node) == ParseNodeKind::ReturnType());
  186. auto subtree = ParseSubtreeConsumer::ForParent(parse_tree(), node);
  187. return TransformExpression(subtree.RequireConsume());
  188. }
  189. } // namespace Carbon