ソースを参照

Factor code out of templates to reduce compile time of `parse/extract.cpp` (#3561)

Unfortunately, it is a relatively small improvement (~5%, though noisy)
in compile time for that file in my testing.
josh11b 2 年 前
コミット
e94e0f155a
1 ファイル変更77 行追加42 行削除
  1. 77 42
      toolchain/parse/extract.cpp

+ 77 - 42
toolchain/parse/extract.cpp

@@ -55,6 +55,28 @@ struct Extractable<NodeId> {
   }
   }
 };
 };
 
 
+static auto NodeIdForKindAccept(const NodeKind& kind, const Tree* tree,
+                                const Tree::SiblingIterator& it,
+                                Tree::SiblingIterator end, ErrorBuilder* trace)
+    -> bool {
+  if (it == end || tree->node_kind(*it) != kind) {
+    if (trace) {
+      if (it == end) {
+        *trace << "NodeIdForKind error: no more children, expected " << kind
+               << "\n";
+      } else {
+        *trace << "NodeIdForKind error: wrong kind " << tree->node_kind(*it)
+               << ", expected " << kind << "\n";
+      }
+    }
+    return false;
+  }
+  if (trace) {
+    *trace << "NodeIdForKind: " << kind << " consumed\n";
+  }
+  return true;
+}
+
 // Extract a `FooId`, which is the same as `NodeIdForKind<NodeKind::Foo>`,
 // Extract a `FooId`, which is the same as `NodeIdForKind<NodeKind::Foo>`,
 // as a single required child.
 // as a single required child.
 template <const NodeKind& Kind>
 template <const NodeKind& Kind>
@@ -62,24 +84,35 @@ struct Extractable<NodeIdForKind<Kind>> {
   static auto Extract(const Tree* tree, Tree::SiblingIterator& it,
   static auto Extract(const Tree* tree, Tree::SiblingIterator& it,
                       Tree::SiblingIterator end, ErrorBuilder* trace)
                       Tree::SiblingIterator end, ErrorBuilder* trace)
       -> std::optional<NodeIdForKind<Kind>> {
       -> std::optional<NodeIdForKind<Kind>> {
-    if (it == end || tree->node_kind(*it) != Kind) {
-      if (trace) {
-        if (it == end) {
-          *trace << "NodeIdForKind error: no more children, expected " << Kind
-                 << "\n";
-        } else {
-          *trace << "NodeIdForKind error: wrong kind " << tree->node_kind(*it)
-                 << ", expected " << Kind << "\n";
-        }
-      }
+    if (NodeIdForKindAccept(Kind, tree, it, end, trace)) {
+      return NodeIdForKind<Kind>(*it++);
+    } else {
       return std::nullopt;
       return std::nullopt;
     }
     }
+  }
+};
+
+static auto NodeIdInCategoryAccept(NodeCategory category, const Tree* tree,
+                                   const Tree::SiblingIterator& it,
+                                   Tree::SiblingIterator end,
+                                   ErrorBuilder* trace) -> bool {
+  if (it == end || !(tree->node_kind(*it).category() & category)) {
     if (trace) {
     if (trace) {
-      *trace << "NodeIdForKind: " << Kind << " consumed\n";
+      *trace << "NodeIdInCategory " << category << " error: ";
+      if (it == end) {
+        *trace << "no more children\n";
+      } else {
+        *trace << "kind " << tree->node_kind(*it) << " doesn't match\n";
+      }
     }
     }
-    return NodeIdForKind<Kind>(*it++);
+    return false;
   }
   }
-};
+  if (trace) {
+    *trace << "NodeIdInCategory " << category << ": kind "
+           << tree->node_kind(*it) << " consumed\n";
+  }
+  return true;
+}
 
 
 // Extract a `NodeIdInCategory<Category>` as a single child.
 // Extract a `NodeIdInCategory<Category>` as a single child.
 template <NodeCategory Category>
 template <NodeCategory Category>
@@ -87,24 +120,38 @@ struct Extractable<NodeIdInCategory<Category>> {
   static auto Extract(const Tree* tree, Tree::SiblingIterator& it,
   static auto Extract(const Tree* tree, Tree::SiblingIterator& it,
                       Tree::SiblingIterator end, ErrorBuilder* trace)
                       Tree::SiblingIterator end, ErrorBuilder* trace)
       -> std::optional<NodeIdInCategory<Category>> {
       -> std::optional<NodeIdInCategory<Category>> {
-    if (it == end || !(tree->node_kind(*it).category() & Category)) {
-      if (trace) {
-        *trace << "NodeIdInCategory " << Category << " error: ";
-        if (it == end) {
-          *trace << "no more children\n";
-        } else {
-          *trace << "kind " << tree->node_kind(*it) << " doesn't match\n";
-        }
-      }
+    if (NodeIdInCategoryAccept(Category, tree, it, end, trace)) {
+      return NodeIdInCategory<Category>(*it++);
+    } else {
       return std::nullopt;
       return std::nullopt;
     }
     }
+  }
+};
+
+static auto NodeIdForKindAccept(NodeKind kind1, NodeKind kind2,
+                                const Tree* tree,
+                                const Tree::SiblingIterator& it,
+                                Tree::SiblingIterator end, ErrorBuilder* trace)
+    -> bool {
+  auto kind = tree->node_kind(*it);
+  if (it == end || (kind != kind1 && kind != kind2)) {
     if (trace) {
     if (trace) {
-      *trace << "NodeIdInCategory " << Category << ": kind "
-             << tree->node_kind(*it) << " consumed\n";
+      if (it == end) {
+        *trace << "NodeIdOneOf error: no more children, expected " << kind1
+               << " or " << kind2 << "\n";
+      } else {
+        *trace << "NodeIdOneOf error: wrong kind " << tree->node_kind(*it)
+               << ", expected " << kind1 << " or " << kind2 << "\n";
+      }
     }
     }
-    return NodeIdInCategory<Category>(*it++);
+    return false;
   }
   }
-};
+  if (trace) {
+    *trace << "NodeIdOneOf " << kind1 << " or " << kind2 << ": "
+           << tree->node_kind(*it) << " consumed\n";
+  }
+  return true;
+}
 
 
 // Extract a `NodeIdOneOf<T, U>` as a single required child.
 // Extract a `NodeIdOneOf<T, U>` as a single required child.
 template <typename T, typename U>
 template <typename T, typename U>
@@ -112,28 +159,16 @@ struct Extractable<NodeIdOneOf<T, U>> {
   static auto Extract(const Tree* tree, Tree::SiblingIterator& it,
   static auto Extract(const Tree* tree, Tree::SiblingIterator& it,
                       Tree::SiblingIterator end, ErrorBuilder* trace)
                       Tree::SiblingIterator end, ErrorBuilder* trace)
       -> std::optional<NodeIdOneOf<T, U>> {
       -> std::optional<NodeIdOneOf<T, U>> {
-    auto kind = tree->node_kind(*it);
-    if (it == end || (kind != T::Kind && kind != U::Kind)) {
-      if (trace) {
-        if (it == end) {
-          *trace << "NodeIdOneOf error: no more children, expected " << T::Kind
-                 << " or " << U::Kind << "\n";
-        } else {
-          *trace << "NodeIdOneOf error: wrong kind " << tree->node_kind(*it)
-                 << ", expected " << T::Kind << " or " << U::Kind << "\n";
-        }
-      }
+    if (NodeIdForKindAccept(T::Kind, U::Kind, tree, it, end, trace)) {
+      return NodeIdOneOf<T, U>(*it++);
+    } else {
       return std::nullopt;
       return std::nullopt;
     }
     }
-    if (trace) {
-      *trace << "NodeIdOneOf " << T::Kind << " or " << U::Kind << ": "
-             << tree->node_kind(*it) << " consumed\n";
-    }
-    return NodeIdOneOf<T, U>(*it++);
   }
   }
 };
 };
 
 
 // Extract a `NodeIdNot<T>` as a single required child.
 // Extract a `NodeIdNot<T>` as a single required child.
+// Note: this is only instantiated once, so no need to create a helper function.
 template <typename T>
 template <typename T>
 struct Extractable<NodeIdNot<T>> {
 struct Extractable<NodeIdNot<T>> {
   static auto Extract(const Tree* tree, Tree::SiblingIterator& it,
   static auto Extract(const Tree* tree, Tree::SiblingIterator& it,