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/ParseContext.h b/src/compiler/translator/ParseContext.h
index c2c4bf2..aeb901c 100644
--- a/src/compiler/translator/ParseContext.h
+++ b/src/compiler/translator/ParseContext.h
@@ -94,8 +94,8 @@
                          const char *token,
                          const char *extraInfo = "");
 
-    TIntermNode *getTreeRoot() const { return mTreeRoot; }
-    void setTreeRoot(TIntermNode *treeRoot) { mTreeRoot = treeRoot; }
+    TIntermBlock *getTreeRoot() const { return mTreeRoot; }
+    void setTreeRoot(TIntermBlock *treeRoot) { mTreeRoot = treeRoot; }
 
     bool getFragmentPrecisionHigh() const
     {
@@ -268,7 +268,7 @@
                                                       const TSourceLoc &location);
     TIntermAggregate *addFunctionDefinition(const TFunction &function,
                                             TIntermAggregate *functionPrototype,
-                                            TIntermAggregate *functionBody,
+                                            TIntermBlock *functionBody,
                                             const TSourceLoc &location);
     void parseFunctionPrototype(const TSourceLoc &location,
                                 TFunction *function,
@@ -335,7 +335,9 @@
 
     void checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field);
 
-    TIntermSwitch *addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc);
+    TIntermSwitch *addSwitch(TIntermTyped *init,
+                             TIntermBlock *statementList,
+                             const TSourceLoc &loc);
     TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc);
     TIntermCase *addDefault(const TSourceLoc &loc);
 
@@ -410,7 +412,7 @@
     ShShaderSpec mShaderSpec;  // The language specification compiler conforms to - GLES2 or WebGL.
     ShCompileOptions mCompileOptions;  // Options passed to TCompiler
     int mShaderVersion;
-    TIntermNode *mTreeRoot;      // root of parse tree being created
+    TIntermBlock *mTreeRoot;     // root of parse tree being created
     int mLoopNestingLevel;       // 0 if outside all loops
     int mStructNestingLevel;     // incremented while parsing a struct declaration
     int mSwitchNestingLevel;     // 0 if outside all switch statements