Accept equality and assignment for arrays in parsing

This is enough to support the operations in GLSL output. HLSL output will
likely require additional work to support this.

BUG=angleproject:941

Change-Id: I728d511ab07af94bc3382dc2796c1e9ac79d1442
Reviewed-on: https://chromium-review.googlesource.com/260801
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index 22d0284..234f3c7 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -387,8 +387,7 @@
 //
 bool TIntermBinary::promote(TInfoSink &infoSink)
 {
-    // This function only handles scalars, vectors, and matrices.
-    ASSERT(!mLeft->isArray() && !mRight->isArray());
+    ASSERT(mLeft->isArray() == mRight->isArray());
 
     // GLSL ES 2.0 does not support implicit type casting.
     // So the basic type should usually match.
@@ -670,6 +669,11 @@
                 mLeft->getSecondarySize(), mRight->getSecondarySize());
             setType(TType(basicType, higherPrecision, EvqTemporary,
                           nominalSize, secondarySize));
+            if (mLeft->isArray())
+            {
+                ASSERT(mLeft->getArraySize() == mRight->getArraySize());
+                mType.setArraySize(mLeft->getArraySize());
+            }
         }
         break;
 
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index 29ce37b..7390b1a 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -1393,7 +1393,16 @@
 
     switch (node->getOp())
     {
-      case EOpAssign:                  outputTriplet(visit, "(", " = ", ")");           break;
+      case EOpAssign:
+        if (node->getLeft()->isArray())
+        {
+            UNIMPLEMENTED();
+        }
+        else
+        {
+            outputTriplet(visit, "(", " = ", ")");
+        }
+        break;
       case EOpInitialize:
         if (visit == PreVisit)
         {
@@ -1565,7 +1574,11 @@
       case EOpBitwiseOr:         outputTriplet(visit, "(", " | ", ")"); break;
       case EOpEqual:
       case EOpNotEqual:
-        if (node->getLeft()->isScalar())
+        if (node->getLeft()->isArray())
+        {
+            UNIMPLEMENTED();
+        }
+        else if (node->getLeft()->isScalar())
         {
             if (node->getOp() == EOpEqual)
             {
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 15fa778..a3fd403 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -2721,8 +2721,34 @@
 {
     if (left->isArray() || right->isArray())
     {
-        error(loc, "Invalid operation for arrays", GetOperatorString(op));
-        return false;
+        if (shaderVersion < 300)
+        {
+            error(loc, "Invalid operation for arrays", GetOperatorString(op));
+            return false;
+        }
+
+        if (left->isArray() != right->isArray())
+        {
+            error(loc, "array / non-array mismatch", GetOperatorString(op));
+            return false;
+        }
+
+        switch (op)
+        {
+          case EOpEqual:
+          case EOpNotEqual:
+          case EOpAssign:
+          case EOpInitialize:
+            break;
+          default:
+            error(loc, "Invalid operation for arrays", GetOperatorString(op));
+            return false;
+        }
+        if (left->getArraySize() != right->getArraySize())
+        {
+            error(loc, "array size mismatch", GetOperatorString(op));
+            return false;
+        }
     }
     return true;
 }