Split TIntermBlock from TIntermAggregate

The new TIntermBlock node class replaces TIntermAggregate nodes with
the EOpSequence op. It represents the root node of the tree which is
a list of declarations and function definitions, and any code blocks
that can be denoted by curly braces. These include function and loop
bodies, and if-else branches.

This change enables a bunch of more compile-time type checking, and
makes the AST code easier to understand and less error-prone.

The PostProcess step that used to be done to ensure that the root node
is TIntermAggregate is removed in favor of making sure that the root
node is a TIntermBlock in the glslang.y parsing code.

Intermediate output formatting is improved to print the EOpNull error
in a clearer way.

After this patch, TIntermAggregate is still used for function
definitions, function prototypes, function parameter lists, function
calls, variable and invariant declarations and the comma (sequence)
operator.

BUG=angleproject:1490
TEST=angle_unittests, angle_end2end_tests

Change-Id: I04044affff979a11577bc1fe75d747e538b799c8
Reviewed-on: https://chromium-review.googlesource.com/393726
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index 32db9de..ecd47fa 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -24,8 +24,11 @@
 {
     if (const TIntermAggregate *aggregate = node->getAsAggregate())
     {
-        return (aggregate->getOp() != EOpFunction) &&
-               (aggregate->getOp() != EOpSequence);
+        return (aggregate->getOp() != EOpFunction);
+    }
+    else if (node->getAsBlock())
+    {
+        return false;
     }
     else if (node->getAsIfElseNode())
     {
@@ -753,6 +756,36 @@
     }
 }
 
+bool TOutputGLSLBase::visitBlock(Visit visit, TIntermBlock *node)
+{
+    TInfoSinkBase &out = objSink();
+    // Scope the blocks except when at the global scope.
+    if (mDepth > 0)
+    {
+        out << "{\n";
+    }
+
+    incrementDepth(node);
+    for (TIntermSequence::const_iterator iter = node->getSequence()->begin();
+         iter != node->getSequence()->end(); ++iter)
+    {
+        TIntermNode *curNode = *iter;
+        ASSERT(curNode != nullptr);
+        curNode->traverse(this);
+
+        if (isSingleStatement(curNode))
+            out << ";\n";
+    }
+    decrementDepth();
+
+    // Scope the blocks except when at the global scope.
+    if (mDepth > 0)
+    {
+        out << "}\n";
+    }
+    return false;
+}
+
 bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
 {
     bool visitChildren = true;
@@ -760,33 +793,6 @@
     bool useEmulatedFunction = (visit == PreVisit && node->getUseEmulatedFunction());
     switch (node->getOp())
     {
-      case EOpSequence:
-        // Scope the sequences except when at the global scope.
-        if (mDepth > 0)
-        {
-            out << "{\n";
-        }
-
-        incrementDepth(node);
-        for (TIntermSequence::const_iterator iter = node->getSequence()->begin();
-             iter != node->getSequence()->end(); ++iter)
-        {
-            TIntermNode *curNode = *iter;
-            ASSERT(curNode != NULL);
-            curNode->traverse(this);
-
-            if (isSingleStatement(curNode))
-                out << ";\n";
-        }
-        decrementDepth();
-
-        // Scope the sequences except when at the global scope.
-        if (mDepth > 0)
-        {
-            out << "}\n";
-        }
-        visitChildren = false;
-        break;
       case EOpPrototype:
         // Function declaration.
         ASSERT(visit == PreVisit);
@@ -830,7 +836,7 @@
         params->traverse(this);
 
         // Traverse function body.
-        TIntermAggregate *body = sequence[1]->getAsAggregate();
+        TIntermBlock *body = sequence[1]->getAsBlock();
         visitCodeBlock(body);
         decrementDepth();
 
@@ -1106,7 +1112,7 @@
     return true;
 }
 
-void TOutputGLSLBase::visitCodeBlock(TIntermNode *node)
+void TOutputGLSLBase::visitCodeBlock(TIntermBlock *node)
 {
     TInfoSinkBase &out = objSink();
     if (node != NULL)