Represent array constructors with a dedicated ConstructorArray class.

Change-Id: Ia8c8a3476202257ecc100f9cb31e6d0095135aa1
Bug: skia:11032
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/391919
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/sksl/SkSLMetalCodeGenerator.cpp b/src/sksl/SkSLMetalCodeGenerator.cpp
index 6e513b7..60148cd 100644
--- a/src/sksl/SkSLMetalCodeGenerator.cpp
+++ b/src/sksl/SkSLMetalCodeGenerator.cpp
@@ -10,6 +10,8 @@
 #include "src/core/SkScopeExit.h"
 #include "src/sksl/SkSLCompiler.h"
 #include "src/sksl/SkSLMemoryLayout.h"
+#include "src/sksl/ir/SkSLConstructorArray.h"
+#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
 #include "src/sksl/ir/SkSLExpressionStatement.h"
 #include "src/sksl/ir/SkSLExtension.h"
 #include "src/sksl/ir/SkSLIndexExpression.h"
@@ -171,6 +173,9 @@
         case Expression::Kind::kConstructor:
             this->writeConstructor(expr.as<Constructor>(), parentPrecedence);
             break;
+        case Expression::Kind::kConstructorArray:
+            this->writeConstructorArray(expr.as<ConstructorArray>(), parentPrecedence);
+            break;
         case Expression::Kind::kConstructorDiagonalMatrix:
             this->writeSingleArgumentConstructor(expr.as<ConstructorDiagonalMatrix>(),
                                                  parentPrecedence);
@@ -1041,6 +1046,8 @@
 
 void MetalCodeGenerator::writeConstructor(const Constructor& c, Precedence parentPrecedence) {
     const Type& constructorType = c.type();
+    SkASSERT(!constructorType.isArray());
+
     // Handle special cases for single-argument constructors.
     if (c.arguments().size() == 1) {
         // If the type is coercible, emit it directly.
@@ -1082,7 +1089,7 @@
 
     // Explicitly invoke the constructor, passing in the necessary arguments.
     this->writeType(constructorType);
-    this->write(constructorType.isArray() ? "{" : "(");
+    this->write("(");
     const char* separator = "";
     int scalarCount = 0;
     for (const std::unique_ptr<Expression>& arg : c.arguments()) {
@@ -1105,7 +1112,7 @@
             scalarCount = 0;
         }
     }
-    this->write(constructorType.isArray() ? "}" : ")");
+    this->write(")");
 }
 
 void MetalCodeGenerator::writeSingleArgumentConstructor(const SingleArgumentConstructor& c,
@@ -1116,6 +1123,19 @@
     this->write(")");
 }
 
+void MetalCodeGenerator::writeConstructorArray(const ConstructorArray& c,
+                                               Precedence parentPrecedence) {
+    this->writeType(c.type());
+    this->write("{");
+    const char* separator = "";
+    for (const std::unique_ptr<Expression>& arg : c.arguments()) {
+        this->write(separator);
+        separator = ", ";
+        this->writeExpression(*arg, Precedence::kSequence);
+    }
+    this->write("}");
+}
+
 void MetalCodeGenerator::writeFragCoord() {
     if (fRTHeightName.length()) {
         this->write("float4(_fragCoord.x, ");
@@ -2238,17 +2258,16 @@
             }
             return result;
         }
-        case Expression::Kind::kConstructor: {
-            const Constructor& c = e->as<Constructor>();
+        case Expression::Kind::kConstructor:
+        case Expression::Kind::kConstructorArray:
+        case Expression::Kind::kConstructorDiagonalMatrix: {
+            const AnyConstructor& c = e->asAnyConstructor();
             Requirements result = kNo_Requirements;
             for (const auto& arg : c.argumentSpan()) {
                 result |= this->requirements(arg.get());
             }
             return result;
         }
-        case Expression::Kind::kConstructorDiagonalMatrix: {
-            return this->requirements(e->as<ConstructorDiagonalMatrix>().argument().get());
-        }
         case Expression::Kind::kFieldAccess: {
             const FieldAccess& f = e->as<FieldAccess>();
             if (FieldAccess::OwnerKind::kAnonymousInterfaceBlock == f.ownerKind()) {