Migrate IsConstantExpression out of SkSLAnalysis.

Change-Id: I08717dd9e9ad20a18a623e06f0c66a0f697effa4
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/456796
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/sksl/SkSLAnalysis.cpp b/src/sksl/SkSLAnalysis.cpp
index dd44f77..d637fbb 100644
--- a/src/sksl/SkSLAnalysis.cpp
+++ b/src/sksl/SkSLAnalysis.cpp
@@ -477,84 +477,6 @@
     }
 }
 
-// Checks for ES2 constant-expression rules, and (optionally) constant-index-expression rules
-// (if loopIndices is non-nullptr)
-class ConstantExpressionVisitor : public ProgramVisitor {
-public:
-    ConstantExpressionVisitor(const std::set<const Variable*>* loopIndices)
-            : fLoopIndices(loopIndices) {}
-
-    bool visitExpression(const Expression& e) override {
-        // A constant-(index)-expression is one of...
-        switch (e.kind()) {
-            // ... a literal value
-            case Expression::Kind::kLiteral:
-                return false;
-
-            // ... settings can appear in fragment processors; they will resolve when compiled
-            case Expression::Kind::kSetting:
-                return false;
-
-            // ... a global or local variable qualified as 'const', excluding function parameters.
-            // ... loop indices as defined in section 4. [constant-index-expression]
-            case Expression::Kind::kVariableReference: {
-                const Variable* v = e.as<VariableReference>().variable();
-                if ((v->storage() == Variable::Storage::kGlobal ||
-                     v->storage() == Variable::Storage::kLocal) &&
-                    (v->modifiers().fFlags & Modifiers::kConst_Flag)) {
-                    return false;
-                }
-                return !fLoopIndices || fLoopIndices->find(v) == fLoopIndices->end();
-            }
-
-            // ... expressions composed of both of the above
-            case Expression::Kind::kBinary:
-            case Expression::Kind::kConstructorArray:
-            case Expression::Kind::kConstructorArrayCast:
-            case Expression::Kind::kConstructorCompound:
-            case Expression::Kind::kConstructorCompoundCast:
-            case Expression::Kind::kConstructorDiagonalMatrix:
-            case Expression::Kind::kConstructorMatrixResize:
-            case Expression::Kind::kConstructorScalarCast:
-            case Expression::Kind::kConstructorSplat:
-            case Expression::Kind::kConstructorStruct:
-            case Expression::Kind::kFieldAccess:
-            case Expression::Kind::kIndex:
-            case Expression::Kind::kPrefix:
-            case Expression::Kind::kPostfix:
-            case Expression::Kind::kSwizzle:
-            case Expression::Kind::kTernary:
-                return INHERITED::visitExpression(e);
-
-            // Function calls are completely disallowed in SkSL constant-(index)-expressions.
-            // GLSL does mandate that calling a built-in function where the arguments are all
-            // constant-expressions should result in a constant-expression. SkSL handles this by
-            // optimizing fully-constant function calls into literals in FunctionCall::Make.
-            case Expression::Kind::kFunctionCall:
-            case Expression::Kind::kExternalFunctionCall:
-            case Expression::Kind::kChildCall:
-
-            // These shouldn't appear in a valid program at all, and definitely aren't
-            // constant-index-expressions.
-            case Expression::Kind::kPoison:
-            case Expression::Kind::kFunctionReference:
-            case Expression::Kind::kExternalFunctionReference:
-            case Expression::Kind::kMethodReference:
-            case Expression::Kind::kTypeReference:
-            case Expression::Kind::kCodeString:
-                return true;
-
-            default:
-                SkDEBUGFAIL("Unexpected expression type");
-                return true;
-        }
-    }
-
-private:
-    const std::set<const Variable*>* fLoopIndices;
-    using INHERITED = ProgramVisitor;
-};
-
 class ES2IndexingVisitor : public ProgramVisitor {
 public:
     ES2IndexingVisitor(ErrorReporter& errors) : fErrors(errors) {}
@@ -576,8 +498,7 @@
     bool visitExpression(const Expression& e) override {
         if (e.is<IndexExpression>()) {
             const IndexExpression& i = e.as<IndexExpression>();
-            ConstantExpressionVisitor indexerInvalid(&fLoopIndices);
-            if (indexerInvalid.visitExpression(*i.index())) {
+            if (!Analysis::IsConstantIndexExpression(*i.index(), &fLoopIndices)) {
                 fErrors.error(i.fLine, "index expression must be constant");
                 return true;
             }
@@ -593,17 +514,11 @@
     using INHERITED = ProgramVisitor;
 };
 
-
 void Analysis::ValidateIndexingForES2(const ProgramElement& pe, ErrorReporter& errors) {
     ES2IndexingVisitor visitor(errors);
     visitor.visitProgramElement(pe);
 }
 
-bool Analysis::IsConstantExpression(const Expression& expr) {
-    ConstantExpressionVisitor visitor(/*loopIndices=*/nullptr);
-    return !visitor.visitExpression(expr);
-}
-
 void Analysis::VerifyStaticTestsAndExpressions(const Program& program) {
     class TestsAndExpressions : public ProgramVisitor {
     public: