Modernize SkRecordPattern.h

  - Fold Or, Or3, Or4 into one flexible Or.
  - Fold Pattern1...Pattern7 into one flexible Pattern.
  - Rename Star Greedy

Still fighting with a flexible get<N>() method instead of first, second, third, etc.

BUG=skia:

Review URL: https://codereview.chromium.org/1465443002
diff --git a/src/core/SkRecordOpts.cpp b/src/core/SkRecordOpts.cpp
index 04c72c3..d363712 100644
--- a/src/core/SkRecordOpts.cpp
+++ b/src/core/SkRecordOpts.cpp
@@ -27,33 +27,33 @@
 }
 
 // Most of the optimizations in this file are pattern-based.  These are all defined as structs with:
-//   - a Pattern typedef
-//   - a bool onMatch(SkRceord*, Pattern*, int begin, int end) method,
+//   - a Match typedef
+//   - a bool onMatch(SkRceord*, Match*, int begin, int end) method,
 //     which returns true if it made changes and false if not.
 
 // Run a pattern-based optimization once across the SkRecord, returning true if it made any changes.
-// It looks for spans which match Pass::Pattern, and when found calls onMatch() with the pattern,
+// It looks for spans which match Pass::Match, and when found calls onMatch() with that pattern,
 // record, and [begin,end) span of the commands that matched.
 template <typename Pass>
 static bool apply(Pass* pass, SkRecord* record) {
-    typename Pass::Pattern pattern;
+    typename Pass::Match match;
     bool changed = false;
     int begin, end = 0;
 
-    while (pattern.search(record, &begin, &end)) {
-        changed |= pass->onMatch(record, &pattern, begin, end);
+    while (match.search(record, &begin, &end)) {
+        changed |= pass->onMatch(record, &match, begin, end);
     }
     return changed;
 }
 
 // Turns the logical NoOp Save and Restore in Save-Draw*-Restore patterns into actual NoOps.
 struct SaveOnlyDrawsRestoreNooper {
-    typedef Pattern3<Is<Save>,
-                     Star<Or<Is<NoOp>, IsDraw> >,
-                     Is<Restore> >
-        Pattern;
+    typedef Pattern<Is<Save>,
+                    Greedy<Or<Is<NoOp>, IsDraw>>,
+                    Is<Restore>>
+        Match;
 
-    bool onMatch(SkRecord* record, Pattern* pattern, int begin, int end) {
+    bool onMatch(SkRecord* record, Match*, int begin, int end) {
         record->replace<NoOp>(begin);  // Save
         record->replace<NoOp>(end-1);  // Restore
         return true;
@@ -119,17 +119,17 @@
 
 // Turns logical no-op Save-[non-drawing command]*-Restore patterns into actual no-ops.
 struct SaveNoDrawsRestoreNooper {
-    // Star matches greedily, so we also have to exclude Save and Restore.
+    // Greedy matches greedily, so we also have to exclude Save and Restore.
     // Nested SaveLayers need to be excluded, or we'll match their Restore!
-    typedef Pattern3<Is<Save>,
-                     Star<Not<Or4<Is<Save>,
+    typedef Pattern<Is<Save>,
+                    Greedy<Not<Or<Is<Save>,
                                   Is<SaveLayer>,
                                   Is<Restore>,
-                                  IsDraw> > >,
-                     Is<Restore> >
-        Pattern;
+                                  IsDraw>>>,
+                    Is<Restore>>
+        Match;
 
-    bool onMatch(SkRecord* record, Pattern* pattern, int begin, int end) {
+    bool onMatch(SkRecord* record, Match*, int begin, int end) {
         // The entire span between Save and Restore (inclusively) does nothing.
         for (int i = begin; i < end; i++) {
             record->replace<NoOp>(i);
@@ -148,17 +148,17 @@
 // For some SaveLayer-[drawing command]-Restore patterns, merge the SaveLayer's alpha into the
 // draw, and no-op the SaveLayer and Restore.
 struct SaveLayerDrawRestoreNooper {
-    typedef Pattern3<Is<SaveLayer>, IsDraw, Is<Restore> > Pattern;
+    typedef Pattern<Is<SaveLayer>, IsDraw, Is<Restore>> Match;
 
-    bool onMatch(SkRecord* record, Pattern* pattern, int begin, int end) {
+    bool onMatch(SkRecord* record, Match* match, int begin, int end) {
         // A SaveLayer's bounds field is just a hint, so we should be free to ignore it.
-        SkPaint* layerPaint = pattern->first<SaveLayer>()->paint;
+        SkPaint* layerPaint = match->first<SaveLayer>()->paint;
         if (nullptr == layerPaint) {
             // There wasn't really any point to this SaveLayer at all.
             return KillSaveLayerAndRestore(record, begin);
         }
 
-        SkPaint* drawPaint = pattern->second<SkPaint>();
+        SkPaint* drawPaint = match->second<SkPaint>();
         if (drawPaint == nullptr) {
             // We can just give the draw the SaveLayer's paint.
             // TODO(mtklein): figure out how to do this clearly
@@ -194,11 +194,11 @@
   Restore
 */
 struct SvgOpacityAndFilterLayerMergePass {
-    typedef Pattern7<Is<SaveLayer>, Is<Save>, Is<ClipRect>, Is<SaveLayer>,
-                     Is<Restore>, Is<Restore>, Is<Restore> > Pattern;
+    typedef Pattern<Is<SaveLayer>, Is<Save>, Is<ClipRect>, Is<SaveLayer>,
+                    Is<Restore>, Is<Restore>, Is<Restore>> Match;
 
-    bool onMatch(SkRecord* record, Pattern* pattern, int begin, int end) {
-        SkPaint* opacityPaint = pattern->first<SaveLayer>()->paint;
+    bool onMatch(SkRecord* record, Match* match, int begin, int end) {
+        SkPaint* opacityPaint = match->first<SaveLayer>()->paint;
         if (nullptr == opacityPaint) {
             // There wasn't really any point to this SaveLayer at all.
             return KillSaveLayerAndRestore(record, begin);
@@ -206,7 +206,7 @@
 
         // This layer typically contains a filter, but this should work for layers with for other
         // purposes too.
-        SkPaint* filterLayerPaint = pattern->fourth<SaveLayer>()->paint;
+        SkPaint* filterLayerPaint = match->fourth<SaveLayer>()->paint;
         if (filterLayerPaint == nullptr) {
             // We can just give the inner SaveLayer the paint of the outer SaveLayer.
             // TODO(mtklein): figure out how to do this clearly
diff --git a/src/core/SkRecordPattern.h b/src/core/SkRecordPattern.h
index d9568b3..9493bbf 100644
--- a/src/core/SkRecordPattern.h
+++ b/src/core/SkRecordPattern.h
@@ -80,44 +80,48 @@
     bool operator()(T* ptr) { return !Matcher()(ptr); }
 };
 
-// Matches if either of A or B does.  Stores nothing.
-template <typename A, typename B>
+// Matches if any of First or Rest... does.  Stores nothing.
+template <typename First, typename... Rest>
 struct Or {
     template <typename T>
-    bool operator()(T* ptr) { return A()(ptr) || B()(ptr); }
+    bool operator()(T* ptr) { return First()(ptr) || Or<Rest...>()(ptr); }
+};
+template <typename First>
+struct Or<First> {
+    template <typename T>
+    bool operator()(T* ptr) { return First()(ptr); }
 };
 
-// Matches if any of A, B or C does.  Stores nothing.
-template <typename A, typename B, typename C>
-struct Or3 : Or<A, Or<B, C> > {};
 
-// Matches if any of A, B, C or D does.  Stores nothing.
-template <typename A, typename B, typename C, typename D>
-struct Or4 : Or<A, Or<B, Or<C, D> > > {};
-
-// Star is a special matcher that greedily matches Matcher 0 or more times.  Stores nothing.
+// Greedy is a special matcher that greedily matches Matcher 0 or more times.  Stores nothing.
 template <typename Matcher>
-struct Star {
+struct Greedy {
     template <typename T>
     bool operator()(T* ptr) { return Matcher()(ptr); }
 };
 
-// Cons builds a list of Matchers.
-// It first matches Matcher (something from above), then Pattern (another Cons or Nil).
+// Pattern matches each of its matchers in order.
 //
 // This is the main entry point to pattern matching, and so provides a couple of extra API bits:
 //  - search scans through the record to look for matches;
-//  - first, second, and third return the data stored by their respective matchers in the pattern.
-//
-// These Cons build lists analogously to Lisp's "cons".  See Pattern# for the "list" equivalent.
-template <typename Matcher, typename Pattern>
-class Cons {
+//  - first, second, third, ... return the data stored by their respective matchers in the pattern.
+
+template <typename... Matchers> class Pattern;
+
+template <> class Pattern<> {
 public:
-    // If this pattern matches the SkRecord starting at i,
+    // Bottoms out recursion.  Just return whatever i the front decided on.
+    int match(SkRecord*, int i) { return i; }
+};
+
+template <typename First, typename... Rest>
+class Pattern<First, Rest...> {
+public:
+    // If this pattern matches the SkRecord starting from i,
     // return the index just past the end of the pattern, otherwise return 0.
     SK_ALWAYS_INLINE int match(SkRecord* record, int i) {
-        i = this->matchHead(&fHead, record, i);
-        return i == 0 ? 0 : fTail.match(record, i);
+        i = this->matchFirst(&fFirst, record, i);
+        return i > 0 ? fRest.match(record, i) : 0;
     }
 
     // Starting from *end, walk through the SkRecord to find the first span matching this pattern.
@@ -132,31 +136,29 @@
         return false;
     }
 
-    // Once either match or search has succeeded, access the stored data of the first, second,
-    // or third matcher in this pattern.  Add as needed for longer patterns.
-    // T is checked statically at compile time; no casting is involved.  It's just an API wart.
-    template <typename T> T* first()  { return fHead.get(); }
-    template <typename T> T* second() { return fTail.fHead.get(); }
-    template <typename T> T* third()  { return fTail.fTail.fHead.get(); }
-    template <typename T> T* fourth()  { return fTail.fTail.fTail.fHead.get(); }
+    // TODO: some sort of smart get<i>()
+    template <typename T> T* first()  { return fFirst.get();   }
+    template <typename T> T* second() { return fRest.template first<T>();  }
+    template <typename T> T* third()  { return fRest.template second<T>(); }
+    template <typename T> T* fourth() { return fRest.template third<T>();  }
 
 private:
-    // If head isn't a Star, try to match at i once.
+    // If first isn't a Greedy, try to match at i once.
     template <typename T>
-    int matchHead(T*, SkRecord* record, int i) {
+    int matchFirst(T* first, SkRecord* record, int i) {
         if (i < record->count()) {
-            if (record->mutate<bool>(i, fHead)) {
+            if (record->mutate<bool>(i, *first)) {
                 return i+1;
             }
         }
         return 0;
     }
 
-    // If head is a Star, walk i until it doesn't match.
+    // If first is a Greedy, walk i until it doesn't match.
     template <typename T>
-    int matchHead(Star<T>*, SkRecord* record, int i) {
+    int matchFirst(Greedy<T>* first, SkRecord* record, int i) {
         while (i < record->count()) {
-            if (!record->mutate<bool>(i, fHead)) {
+            if (!record->mutate<bool>(i, *first)) {
                 return i;
             }
             i++;
@@ -164,43 +166,10 @@
         return 0;
     }
 
-    Matcher fHead;
-    Pattern fTail;
-
-    // All Cons are friends with each other.  This lets first, second, and third work.
-    template <typename, typename> friend class Cons;
+    First            fFirst;
+    Pattern<Rest...> fRest;
 };
 
-// Nil is the end of every pattern Cons chain.
-struct Nil {
-    // Bottoms out recursion down the fTail chain.  Just return whatever i the front decided on.
-    int match(SkRecord*, int i) { return i; }
-};
-
-// These Pattern# types are syntax sugar over Cons and Nil, just to help eliminate some of the
-// template noise.  Use these if you can.  Feel free to add more for longer patterns.
-// All types A, B, C, ... are Matchers.
-template <typename A>
-struct Pattern1 : Cons<A, Nil> {};
-
-template <typename A, typename B>
-struct Pattern2 : Cons<A, Pattern1<B> > {};
-
-template <typename A, typename B, typename C>
-struct Pattern3 : Cons<A, Pattern2<B, C> > {};
-
-template <typename A, typename B, typename C, typename D>
-struct Pattern4 : Cons<A, Pattern3<B, C, D> > {};
-
-template <typename A, typename B, typename C, typename D, typename E>
-struct Pattern5 : Cons<A, Pattern4<B, C, D, E> > {};
-
-template <typename A, typename B, typename C, typename D, typename E, typename F>
-struct Pattern6 : Cons<A, Pattern5<B, C, D, E, F> > {};
-
-template <typename A, typename B, typename C, typename D, typename E, typename F, typename G>
-struct Pattern7 : Cons<A, Pattern6<B, C, D, E, F, G> > {};
-
 }  // namespace SkRecords
 
 #endif//SkRecordPattern_DEFINED
diff --git a/tests/RecordPatternTest.cpp b/tests/RecordPatternTest.cpp
index d1e48bb..33a0114 100644
--- a/tests/RecordPatternTest.cpp
+++ b/tests/RecordPatternTest.cpp
@@ -13,9 +13,9 @@
 #include "SkRecords.h"
 
 using namespace SkRecords;
-typedef Pattern3<Is<Save>,
-                 Is<ClipRect>,
-                 Is<Restore> >
+typedef Pattern<Is<Save>,
+                Is<ClipRect>,
+                Is<Restore>>
     SaveClipRectRestore;
 
 DEF_TEST(RecordPattern_Simple, r) {
@@ -77,8 +77,8 @@
     REPORTER_ASSERT(r, !pattern.match(&record, 0));
 }
 
-DEF_TEST(RecordPattern_Star, r) {
-    Pattern3<Is<Save>, Star<Is<ClipRect> >, Is<Restore> > pattern;
+DEF_TEST(RecordPattern_Greedy, r) {
+    Pattern<Is<Save>, Greedy<Is<ClipRect>>, Is<Restore>> pattern;
 
     SkRecord record;
     SkRecorder recorder(&record, 1920, 1200);
@@ -98,11 +98,11 @@
 }
 
 DEF_TEST(RecordPattern_Complex, r) {
-    Pattern3<Is<Save>,
-             Star<Not<Or3<Is<Save>,
+    Pattern<Is<Save>,
+            Greedy<Not<Or<Is<Save>,
                           Is<Restore>,
-                          IsDraw> > >,
-             Is<Restore> > pattern;
+                          IsDraw>>>,
+            Is<Restore>> pattern;
 
     SkRecord record;
     SkRecorder recorder(&record, 1920, 1200);
@@ -142,7 +142,7 @@
 }
 
 DEF_TEST(RecordPattern_SaveLayerIsNotADraw, r) {
-    Pattern1<IsDraw> pattern;
+    Pattern<IsDraw> pattern;
 
     SkRecord record;
     SkRecorder recorder(&record, 1920, 1200);