Преглед изворни кода

Refactory the IR/builder relationship (#2342)

I'm thinking about how to handle multiple files, and I think the current IRFactory is useful as a file-focused thing. So shifting/renaming accordingly. (doing this in its own PR to make the history a little cleaner for git's move detection)
Jon Ross-Perkins пре 3 година
родитељ
комит
d51ca271af

+ 1 - 1
bazel/check_deps/BUILD

@@ -13,10 +13,10 @@ filegroup(
     data = [
         "//explorer",
         "//installers/local:carbon",
+        "//migrate_cpp:rewriter",
         "//migrate_cpp/cpp_refactoring",
         "//toolchain/diagnostics:null_diagnostics",
         "//toolchain/driver:carbon",
-        "//toolchain/semantics:semantics_ir_factory",
     ],
 )
 

+ 4 - 0
migrate_cpp/BUILD

@@ -36,6 +36,10 @@ cc_library(
         "@llvm-project//clang:tooling_core",
         "@llvm-project//llvm:Support",
     ],
+    visibility = [
+      # For dependency checking. Remove once it has a binary using it.
+      "//bazel/check_deps:__pkg__",
+    ],
 )
 
 cc_test(

+ 1 - 2
toolchain/README.md

@@ -124,8 +124,7 @@ keeping the code simple seems better until the language design stabilizes.
 ## Semantics
 
 The [SemanticsIR](semantics/semantics_ir.h) is the output of semantic
-processing. It's currently built using
-[a factory](semantics/semantics_ir_factory.h).
+processing.
 
 The intent is that a `SemanticsIR` looks closer to a series of instructions than
 a tree. This is in order to better align with the LLVM IR structure which will

+ 1 - 1
toolchain/driver/BUILD

@@ -19,7 +19,7 @@ cc_library(
         "//toolchain/diagnostics:sorting_diagnostic_consumer",
         "//toolchain/lexer:tokenized_buffer",
         "//toolchain/parser:parse_tree",
-        "//toolchain/semantics:semantics_ir_factory",
+        "//toolchain/semantics:semantics_ir",
         "//toolchain/source:source_buffer",
         "@llvm-project//llvm:Support",
     ],

+ 2 - 2
toolchain/driver/driver.cpp

@@ -14,7 +14,7 @@
 #include "toolchain/diagnostics/sorting_diagnostic_consumer.h"
 #include "toolchain/lexer/tokenized_buffer.h"
 #include "toolchain/parser/parse_tree.h"
-#include "toolchain/semantics/semantics_ir_factory.h"
+#include "toolchain/semantics/semantics_ir.h"
 #include "toolchain/source/source_buffer.h"
 
 namespace Carbon {
@@ -162,7 +162,7 @@ auto Driver::RunDumpSubcommand(DiagnosticConsumer& consumer,
     return !tokenized_source.has_errors() && !parse_tree.has_errors();
   }
 
-  auto semantics_ir = SemanticsIRFactory::Build(tokenized_source, parse_tree);
+  SemanticsIR semantics_ir(tokenized_source, parse_tree);
   if (dump_mode == DumpMode::SemanticsIR) {
     consumer.Flush();
     semantics_ir.Print(output_stream_);

+ 2 - 13
toolchain/semantics/BUILD

@@ -18,10 +18,12 @@ cc_library(
 cc_library(
     name = "semantics_ir",
     srcs = [
+        "semantics_parse_tree_handler.cpp",
         "semantics_ir.cpp",
         "semantics_node.cpp",
     ],
     hdrs = [
+        "semantics_parse_tree_handler.h",
         "semantics_ir.h",
         "semantics_node.h",
     ],
@@ -29,19 +31,6 @@ cc_library(
         ":semantics_node_kind",
         "//common:check",
         "//common:ostream",
-        "//toolchain/lexer:tokenized_buffer",
-        "//toolchain/parser:parse_tree",
-        "@llvm-project//llvm:Support",
-    ],
-)
-
-cc_library(
-    name = "semantics_ir_factory",
-    srcs = ["semantics_ir_factory.cpp"],
-    hdrs = ["semantics_ir_factory.h"],
-    deps = [
-        ":semantics_ir",
-        "//common:check",
         "//toolchain/lexer:token_kind",
         "//toolchain/lexer:tokenized_buffer",
         "//toolchain/parser:parse_node_kind",

+ 6 - 0
toolchain/semantics/semantics_ir.cpp

@@ -8,9 +8,15 @@
 #include "llvm/Support/FormatVariadic.h"
 #include "toolchain/lexer/tokenized_buffer.h"
 #include "toolchain/semantics/semantics_node.h"
+#include "toolchain/semantics/semantics_parse_tree_handler.h"
 
 namespace Carbon {
 
+SemanticsIR::SemanticsIR(const TokenizedBuffer& tokens,
+                         const ParseTree& parse_tree) {
+  SemanticsParseTreeHandler(tokens, parse_tree, *this).Build();
+}
+
 auto SemanticsIR::Print(llvm::raw_ostream& out) const -> void {
   out << "identifiers = {\n";
   for (int32_t i = 0; i < static_cast<int32_t>(identifiers_.size()); ++i) {

+ 3 - 6
toolchain/semantics/semantics_ir.h

@@ -19,14 +19,13 @@ namespace Carbon {
 // Provides semantic analysis on a ParseTree.
 class SemanticsIR {
  public:
+  SemanticsIR(const TokenizedBuffer& tokens, const ParseTree& parse_tree);
+
   // Prints the full IR.
   auto Print(llvm::raw_ostream& out) const -> void;
 
  private:
-  friend class SemanticsIRFactory;
-
-  explicit SemanticsIR(const ParseTree& parse_tree)
-      : parse_tree_(&parse_tree) {}
+  friend class SemanticsParseTreeHandler;
 
   auto AddIdentifier(llvm::StringRef identifier) -> SemanticsIdentifierId {
     SemanticsIdentifierId id(identifiers_.size());
@@ -50,8 +49,6 @@ class SemanticsIR {
   llvm::SmallVector<llvm::StringRef> identifiers_;
   llvm::SmallVector<llvm::APInt> integer_literals_;
   llvm::SmallVector<SemanticsNode> nodes_;
-
-  const ParseTree* parse_tree_;
 };
 
 }  // namespace Carbon

+ 26 - 33
toolchain/semantics/semantics_ir_factory.cpp → toolchain/semantics/semantics_parse_tree_handler.cpp

@@ -2,9 +2,7 @@
 // Exceptions. See /LICENSE for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
-#include "toolchain/semantics/semantics_ir_factory.h"
-
-#include <stack>
+#include "toolchain/semantics/semantics_parse_tree_handler.h"
 
 #include "toolchain/lexer/token_kind.h"
 #include "toolchain/lexer/tokenized_buffer.h"
@@ -13,18 +11,11 @@
 
 namespace Carbon {
 
-auto SemanticsIRFactory::Build(const TokenizedBuffer& tokens,
-                               const ParseTree& parse_tree) -> SemanticsIR {
-  SemanticsIRFactory builder(tokens, parse_tree);
-  builder.Build();
-  return builder.semantics_;
-}
-
-void SemanticsIRFactory::Build() {
-  auto range = parse_tree().postorder();
+auto SemanticsParseTreeHandler::Build() -> void {
+  auto range = parse_tree_->postorder();
   for (auto it = range.begin();; ++it) {
     auto parse_node = *it;
-    switch (auto parse_kind = parse_tree().node_kind(parse_node)) {
+    switch (auto parse_kind = parse_tree_->node_kind(parse_node)) {
       case ParseNodeKind::DeclaredName(): {
         HandleDeclaredName(parse_node);
         break;
@@ -41,7 +32,7 @@ void SemanticsIRFactory::Build() {
         ++it;
         CARBON_CHECK(it == range.end())
             << "FileEnd should always be last, found "
-            << parse_tree().node_kind(*it);
+            << parse_tree_->node_kind(*it);
         return;
       }
       case ParseNodeKind::InfixOperator(): {
@@ -76,43 +67,43 @@ void SemanticsIRFactory::Build() {
   llvm_unreachable("Should always end at FileEnd");
 }
 
-auto SemanticsIRFactory::HandleDeclaredName(ParseTree::Node parse_node)
+auto SemanticsParseTreeHandler::HandleDeclaredName(ParseTree::Node parse_node)
     -> void {
-  auto text = parse_tree().GetNodeText(parse_node);
-  auto identifier_id = semantics_.AddIdentifier(text);
+  auto text = parse_tree_->GetNodeText(parse_node);
+  auto identifier_id = semantics_->AddIdentifier(text);
   Push(parse_node, SemanticsNode::MakeIdentifier(identifier_id));
 }
 
-auto SemanticsIRFactory::HandleFunctionDefinition(ParseTree::Node parse_node)
-    -> void {
+auto SemanticsParseTreeHandler::HandleFunctionDefinition(
+    ParseTree::Node parse_node) -> void {
   // Merges code block children up under the FunctionDefinitionStart.
-  while (parse_tree().node_kind(node_stack_.back().parse_node) !=
+  while (parse_tree_->node_kind(node_stack_.back().parse_node) !=
          ParseNodeKind::FunctionDefinitionStart()) {
     node_stack_.pop_back();
   }
   Pop(ParseNodeKind::FunctionDefinitionStart());
-  semantics_.AddNode(SemanticsNode::MakeFunctionDefinitionEnd());
+  semantics_->AddNode(SemanticsNode::MakeFunctionDefinitionEnd());
   Push(parse_node);
 }
 
-auto SemanticsIRFactory::HandleFunctionDefinitionStart(
+auto SemanticsParseTreeHandler::HandleFunctionDefinitionStart(
     ParseTree::Node parse_node) -> void {
   Pop(ParseNodeKind::ParameterList());
   auto name_node_id = PopWithResult(ParseNodeKind::DeclaredName());
   Pop(ParseNodeKind::FunctionIntroducer());
   auto decl_id =
-      semantics_.AddNode(SemanticsNode::MakeFunctionDeclaration(name_node_id));
-  semantics_.AddNode(SemanticsNode::MakeFunctionDefinitionStart(decl_id));
+      semantics_->AddNode(SemanticsNode::MakeFunctionDeclaration(name_node_id));
+  semantics_->AddNode(SemanticsNode::MakeFunctionDefinitionStart(decl_id));
   Push(parse_node);
 }
 
-auto SemanticsIRFactory::HandleInfixOperator(ParseTree::Node parse_node)
+auto SemanticsParseTreeHandler::HandleInfixOperator(ParseTree::Node parse_node)
     -> void {
   auto rhs_id = PopWithResult();
   auto lhs_id = PopWithResult();
 
   // Figure out the operator for the token.
-  auto token = parse_tree().node_token(parse_node);
+  auto token = parse_tree_->node_token(parse_node);
   switch (auto token_kind = tokens_->GetKind(token)) {
     case TokenKind::Plus():
       Push(parse_node, SemanticsNode::MakeBinaryOperatorAdd(lhs_id, rhs_id));
@@ -122,11 +113,13 @@ auto SemanticsIRFactory::HandleInfixOperator(ParseTree::Node parse_node)
   }
 }
 
-auto SemanticsIRFactory::HandleLiteral(ParseTree::Node parse_node) -> void {
-  auto token = parse_tree().node_token(parse_node);
+auto SemanticsParseTreeHandler::HandleLiteral(ParseTree::Node parse_node)
+    -> void {
+  auto token = parse_tree_->node_token(parse_node);
   switch (auto token_kind = tokens_->GetKind(token)) {
     case TokenKind::IntegerLiteral(): {
-      auto id = semantics_.AddIntegerLiteral(tokens_->GetIntegerLiteral(token));
+      auto id =
+          semantics_->AddIntegerLiteral(tokens_->GetIntegerLiteral(token));
       Push(parse_node, SemanticsNode::MakeIntegerLiteral(id));
       break;
     }
@@ -135,7 +128,7 @@ auto SemanticsIRFactory::HandleLiteral(ParseTree::Node parse_node) -> void {
   }
 }
 
-auto SemanticsIRFactory::HandleParameterList(ParseTree::Node parse_node)
+auto SemanticsParseTreeHandler::HandleParameterList(ParseTree::Node parse_node)
     -> void {
   // TODO: This should transform into a usable parameter list. For now
   // it's unused and only stored so that node counts match.
@@ -145,13 +138,13 @@ auto SemanticsIRFactory::HandleParameterList(ParseTree::Node parse_node)
   Push(parse_node);
 }
 
-auto SemanticsIRFactory::HandleReturnStatement(ParseTree::Node parse_node)
-    -> void {
+auto SemanticsParseTreeHandler::HandleReturnStatement(
+    ParseTree::Node parse_node) -> void {
   Pop(ParseNodeKind::StatementEnd());
 
   // TODO: Restructure ReturnStatement so that we can do this without
   // looking at the subtree size.
-  if (parse_tree().node_subtree_size(parse_node) == 2) {
+  if (parse_tree_->node_subtree_size(parse_node) == 2) {
     Push(parse_node, SemanticsNode::MakeReturn());
   } else {
     auto arg = PopWithResult();

+ 21 - 22
toolchain/semantics/semantics_ir_factory.h → toolchain/semantics/semantics_parse_tree_handler.h

@@ -2,8 +2,8 @@
 // Exceptions. See /LICENSE for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
-#ifndef CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_IR_FACTORY_H_
-#define CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_IR_FACTORY_H_
+#ifndef CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_PARSE_TREE_HANDLER_H_
+#define CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_PARSE_TREE_HANDLER_H_
 
 #include "common/check.h"
 #include "toolchain/parser/parse_tree.h"
@@ -11,12 +11,17 @@
 
 namespace Carbon {
 
-// The main semantic analysis entry.
-class SemanticsIRFactory {
+// Handles processing of a ParseTree for semantics.
+class SemanticsParseTreeHandler {
  public:
-  // Builds the SemanticsIR without doing any substantial semantic analysis.
-  static auto Build(const TokenizedBuffer& tokens, const ParseTree& parse_tree)
-      -> SemanticsIR;
+  // Stores references for work.
+  explicit SemanticsParseTreeHandler(const TokenizedBuffer& tokens,
+                                     const ParseTree& parse_tree,
+                                     SemanticsIR& semantics)
+      : tokens_(&tokens), parse_tree_(&parse_tree), semantics_(&semantics) {}
+
+  // Outputs the ParseTree information into SemanticsIR.
+  auto Build() -> void;
 
  private:
   struct TraversalStackEntry {
@@ -24,24 +29,18 @@ class SemanticsIRFactory {
     llvm::Optional<SemanticsNodeId> result_id;
   };
 
-  explicit SemanticsIRFactory(const TokenizedBuffer& tokens,
-                              const ParseTree& parse_tree)
-      : tokens_(&tokens), semantics_(parse_tree) {}
-
-  auto Build() -> void;
-
   auto Push(ParseTree::Node parse_node) -> void {
     node_stack_.push_back({parse_node, llvm::None});
   }
 
   auto Push(ParseTree::Node parse_node, SemanticsNode node) -> void {
-    auto node_id = semantics_.AddNode(node);
+    auto node_id = semantics_->AddNode(node);
     node_stack_.push_back({parse_node, node_id});
   }
 
   auto Pop(ParseNodeKind pop_parse_kind) -> void {
     auto back = node_stack_.back();
-    auto parse_kind = parse_tree().node_kind(back.parse_node);
+    auto parse_kind = parse_tree_->node_kind(back.parse_node);
     CARBON_CHECK(parse_kind == pop_parse_kind)
         << "Expected " << pop_parse_kind << ", found " << parse_kind;
     CARBON_CHECK(!back.result_id) << "Expected no result ID on " << parse_kind;
@@ -57,7 +56,7 @@ class SemanticsIRFactory {
 
   auto PopWithResult(ParseNodeKind pop_parse_kind) -> SemanticsNodeId {
     auto back = node_stack_.back();
-    auto parse_kind = parse_tree().node_kind(back.parse_node);
+    auto parse_kind = parse_tree_->node_kind(back.parse_node);
     auto node_id = *back.result_id;
     CARBON_CHECK(parse_kind == pop_parse_kind)
         << "Expected " << pop_parse_kind << ", found " << parse_kind;
@@ -74,14 +73,14 @@ class SemanticsIRFactory {
   auto HandleParameterList(ParseTree::Node parse_node) -> void;
   auto HandleReturnStatement(ParseTree::Node parse_node) -> void;
 
-  // Convenience accessor.
-  auto parse_tree() -> const ParseTree& { return *semantics_.parse_tree_; }
-
   // Tokens for getting data on literals.
   const TokenizedBuffer* tokens_;
 
-  // The SemanticsIR being constructed.
-  SemanticsIR semantics_;
+  // The file's parse tree.
+  const ParseTree* parse_tree_;
+
+  // The SemanticsIR being added to.
+  SemanticsIR* semantics_;
 
   // The stack during Build. Will contain file-level parse nodes on return.
   llvm::SmallVector<TraversalStackEntry> node_stack_;
@@ -89,4 +88,4 @@ class SemanticsIRFactory {
 
 }  // namespace Carbon
 
-#endif  // CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_IR_FACTORY_H_
+#endif  // CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_PARSE_TREE_HANDLER_H_