Move function prototypes and declarations out of the .y

This will make the code easier to edit and maintain.

BUG=none
TEST=angle_unittests,angle_end2end_tests

Change-Id: I955307d1209170fa99142103bc4d361c9eab1cc8
Reviewed-on: https://chromium-review.googlesource.com/286145
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 1d017ca..46701df 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -1813,6 +1813,166 @@
     }
 }
 
+void TParseContext::parseFunctionPrototype(const TSourceLoc &location,
+                                           TFunction *function,
+                                           TIntermAggregate **aggregateOut)
+{
+    const TSymbol *builtIn = symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
+
+    if (builtIn)
+    {
+        error(location, "built-in functions cannot be redefined", function->getName().c_str());
+        recover();
+    }
+
+    TFunction* prevDec = static_cast<TFunction*>(symbolTable.find(function->getMangledName(), getShaderVersion()));
+    //
+    // Note:  'prevDec' could be 'function' if this is the first time we've seen function
+    // as it would have just been put in the symbol table.  Otherwise, we're looking up
+    // an earlier occurance.
+    //
+    if (prevDec->isDefined())
+    {
+        // Then this function already has a body.
+        error(location, "function already has a body", function->getName().c_str());
+        recover();
+    }
+    prevDec->setDefined();
+    //
+    // Overload the unique ID of the definition to be the same unique ID as the declaration.
+    // Eventually we will probably want to have only a single definition and just swap the
+    // arguments to be the definition's arguments.
+    //
+    function->setUniqueId(prevDec->getUniqueId());
+
+    // Raise error message if main function takes any parameters or return anything other than void
+    if (function->getName() == "main")
+    {
+        if (function->getParamCount() > 0)
+        {
+            error(location, "function cannot take any parameter(s)", function->getName().c_str());
+            recover();
+        }
+        if (function->getReturnType().getBasicType() != EbtVoid)
+        {
+            error(location, "", function->getReturnType().getBasicString(), "main function cannot return a value");
+            recover();
+        }
+    }
+
+    //
+    // Remember the return type for later checking for RETURN statements.
+    //
+    setCurrentFunctionType(&(prevDec->getReturnType()));
+    setFunctionReturnsValue(false);
+
+    //
+    // Insert parameters into the symbol table.
+    // If the parameter has no name, it's not an error, just don't insert it
+    // (could be used for unused args).
+    //
+    // Also, accumulate the list of parameters into the HIL, so lower level code
+    // knows where to find parameters.
+    //
+    TIntermAggregate *paramNodes = new TIntermAggregate;
+    for (size_t i = 0; i < function->getParamCount(); i++)
+    {
+        const TConstParameter &param = function->getParam(i);
+        if (param.name != 0)
+        {
+            TVariable *variable = new TVariable(param.name, *param.type);
+            //
+            // Insert the parameters with name in the symbol table.
+            //
+            if (!symbolTable.declare(variable)) {
+                error(location, "redefinition", variable->getName().c_str());
+                recover();
+                delete variable;
+            }
+
+            //
+            // Add the parameter to the HIL
+            //
+            TIntermSymbol *symbol = intermediate.addSymbol(variable->getUniqueId(),
+                                                           variable->getName(),
+                                                           variable->getType(), location);
+
+            paramNodes = intermediate.growAggregate(paramNodes, symbol, location);
+        }
+        else
+        {
+            paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
+        }
+    }
+    intermediate.setAggregateOperator(paramNodes, EOpParameters, location);
+    *aggregateOut = paramNodes;
+    setLoopNestingLevel(0);
+}
+
+TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location,
+                                                  TFunction *function)
+{
+    //
+    // Multiple declarations of the same function are allowed.
+    //
+    // If this is a definition, the definition production code will check for redefinitions
+    // (we don't know at this point if it's a definition or not).
+    //
+    // Redeclarations are allowed.  But, return types and parameter qualifiers must match.
+    //
+    TFunction *prevDec = static_cast<TFunction*>(symbolTable.find(function->getMangledName(), getShaderVersion()));
+    if (prevDec)
+    {
+        if (prevDec->getReturnType() != function->getReturnType())
+        {
+            error(location,
+                  "overloaded functions must have the same return type",
+                  function->getReturnType().getBasicString());
+            recover();
+        }
+        for (size_t i = 0; i < prevDec->getParamCount(); ++i)
+        {
+            if (prevDec->getParam(i).type->getQualifier() != function->getParam(i).type->getQualifier())
+            {
+                error(location,
+                      "overloaded functions must have the same parameter qualifiers",
+                      function->getParam(i).type->getQualifierString());
+                recover();
+            }
+        }
+    }
+
+    //
+    // Check for previously declared variables using the same name.
+    //
+    TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
+    if (prevSym)
+    {
+        if (!prevSym->isFunction())
+        {
+            error(location, "redefinition", function->getName().c_str(), "function");
+            recover();
+        }
+    }
+    else
+    {
+        // Insert the unmangled name to detect potential future redefinition as a variable.
+        TFunction *newFunction = new TFunction(NewPoolTString(function->getName().c_str()), &function->getReturnType());
+        symbolTable.getOuterLevel()->insertUnmangled(newFunction);
+    }
+
+    // We're at the inner scope level of the function's arguments and body statement.
+    // Add the function prototype to the surrounding scope instead.
+    symbolTable.getOuterLevel()->insert(function);
+
+    //
+    // If this is a redeclaration, it could also be a definition,
+    // in which case, we want to use the variable names from this one, and not the one that's
+    // being redeclared.  So, pass back up this declaration, not the one in the symbol table.
+    //
+    return function;
+}
+
 TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
 {
     TPublicType publicType = publicTypeIn;
diff --git a/src/compiler/translator/ParseContext.h b/src/compiler/translator/ParseContext.h
index 62693f2..c068116 100644
--- a/src/compiler/translator/ParseContext.h
+++ b/src/compiler/translator/ParseContext.h
@@ -220,6 +220,11 @@
                                                TIntermTyped *initializer);
 
     void parseGlobalLayoutQualifier(const TPublicType &typeQualifier);
+    void parseFunctionPrototype(const TSourceLoc &location,
+                                TFunction *function,
+                                TIntermAggregate **aggregateOut);
+    TFunction *parseFunctionDeclarator(const TSourceLoc &location,
+                                       TFunction *function);
     TFunction *addConstructorFunc(const TPublicType &publicType);
     TIntermTyped *addConstructor(TIntermNode *arguments,
                                  TType *type,
diff --git a/src/compiler/translator/glslang.y b/src/compiler/translator/glslang.y
index 0fe574b..5228e5e 100644
--- a/src/compiler/translator/glslang.y
+++ b/src/compiler/translator/glslang.y
@@ -664,57 +664,7 @@
 
 function_prototype
     : function_declarator RIGHT_PAREN  {
-        //
-        // Multiple declarations of the same function are allowed.
-        //
-        // If this is a definition, the definition production code will check for redefinitions
-        // (we don't know at this point if it's a definition or not).
-        //
-        // Redeclarations are allowed.  But, return types and parameter qualifiers must match.
-        //
-        TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find($1->getMangledName(), context->getShaderVersion()));
-        if (prevDec) {
-            if (prevDec->getReturnType() != $1->getReturnType()) {
-                context->error(@2, "overloaded functions must have the same return type", $1->getReturnType().getBasicString());
-                context->recover();
-            }
-            for (size_t i = 0; i < prevDec->getParamCount(); ++i) {
-                if (prevDec->getParam(i).type->getQualifier() != $1->getParam(i).type->getQualifier()) {
-                    context->error(@2, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString());
-                    context->recover();
-                }
-            }
-        }
-
-        //
-        // Check for previously declared variables using the same name.
-        //
-        TSymbol *prevSym = context->symbolTable.find($1->getName(), context->getShaderVersion());
-        if (prevSym)
-        {
-            if (!prevSym->isFunction())
-            {
-                context->error(@2, "redefinition", $1->getName().c_str(), "function");
-                context->recover();
-            }
-        }
-        else
-        {
-            // Insert the unmangled name to detect potential future redefinition as a variable.
-            TFunction *function = new TFunction(NewPoolTString($1->getName().c_str()), &$1->getReturnType());
-            context->symbolTable.getOuterLevel()->insertUnmangled(function);
-        }
-
-        //
-        // If this is a redeclaration, it could also be a definition,
-        // in which case, we want to use the variable names from this one, and not the one that's
-        // being redeclared.  So, pass back up this declaration, not the one in the symbol table.
-        //
-        $$.function = $1;
-
-        // We're at the inner scope level of the function's arguments and body statement.
-        // Add the function prototype to the surrounding scope instead.
-        context->symbolTable.getOuterLevel()->insert($$.function);
+        $$.function = context->parseFunctionDeclarator(@2, $1);
     }
     ;
 
@@ -1665,95 +1615,7 @@
 
 function_definition
     : function_prototype {
-        TFunction* function = $1.function;
-        
-        const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName(), context->getShaderVersion());
-        
-        if (builtIn)
-        {
-            context->error(@1, "built-in functions cannot be redefined", function->getName().c_str());
-            context->recover();
-        }
-        
-        TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName(), context->getShaderVersion()));
-        //
-        // Note:  'prevDec' could be 'function' if this is the first time we've seen function
-        // as it would have just been put in the symbol table.  Otherwise, we're looking up
-        // an earlier occurance.
-        //
-        if (prevDec->isDefined()) {
-            //
-            // Then this function already has a body.
-            //
-            context->error(@1, "function already has a body", function->getName().c_str());
-            context->recover();
-        }
-        prevDec->setDefined();
-        //
-        // Overload the unique ID of the definition to be the same unique ID as the declaration.
-        // Eventually we will probably want to have only a single definition and just swap the
-        // arguments to be the definition's arguments.
-        //
-        function->setUniqueId(prevDec->getUniqueId());
-
-        //
-        // Raise error message if main function takes any parameters or return anything other than void
-        //
-        if (function->getName() == "main") {
-            if (function->getParamCount() > 0) {
-                context->error(@1, "function cannot take any parameter(s)", function->getName().c_str());
-                context->recover();
-            }
-            if (function->getReturnType().getBasicType() != EbtVoid) {
-                context->error(@1, "", function->getReturnType().getBasicString(), "main function cannot return a value");
-                context->recover();
-            }
-        }
-
-        //
-        // Remember the return type for later checking for RETURN statements.
-        //
-        context->setCurrentFunctionType(&(prevDec->getReturnType()));
-        context->setFunctionReturnsValue(false);
-
-        //
-        // Insert parameters into the symbol table.
-        // If the parameter has no name, it's not an error, just don't insert it
-        // (could be used for unused args).
-        //
-        // Also, accumulate the list of parameters into the HIL, so lower level code
-        // knows where to find parameters.
-        //
-        TIntermAggregate* paramNodes = new TIntermAggregate;
-        for (size_t i = 0; i < function->getParamCount(); i++) {
-            const TConstParameter& param = function->getParam(i);
-            if (param.name != 0) {
-                TVariable *variable = new TVariable(param.name, *param.type);
-                //
-                // Insert the parameters with name in the symbol table.
-                //
-                if (! context->symbolTable.declare(variable)) {
-                    context->error(@1, "redefinition", variable->getName().c_str());
-                    context->recover();
-                    delete variable;
-                }
-
-                //
-                // Add the parameter to the HIL
-                //
-                paramNodes = context->intermediate.growAggregate(
-                                               paramNodes,
-                                               context->intermediate.addSymbol(variable->getUniqueId(),
-                                                                       variable->getName(),
-                                                                       variable->getType(), @1),
-                                               @1);
-            } else {
-                paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, @1), @1);
-            }
-        }
-        context->intermediate.setAggregateOperator(paramNodes, EOpParameters, @1);
-        $1.intermAggregate = paramNodes;
-        context->setLoopNestingLevel(0);
+        context->parseFunctionPrototype(@1, $1.function, &$1.intermAggregate);
     }
     compound_statement_no_new_scope {
         //?? Check that all paths return a value if return type != void ?
diff --git a/src/compiler/translator/glslang_tab.cpp b/src/compiler/translator/glslang_tab.cpp
index d9ff7c2..f022874 100644
--- a/src/compiler/translator/glslang_tab.cpp
+++ b/src/compiler/translator/glslang_tab.cpp
@@ -703,25 +703,25 @@
      488,   495,   496,   503,   504,   510,   511,   517,   518,   524,
      525,   531,   532,   540,   541,   542,   543,   547,   548,   549,
      553,   557,   561,   565,   572,   575,   586,   594,   602,   630,
-     636,   647,   651,   655,   659,   666,   722,   725,   732,   740,
-     761,   788,   798,   826,   831,   841,   846,   856,   859,   862,
-     865,   871,   878,   881,   885,   889,   894,   899,   906,   910,
-     914,   918,   923,   928,   932,   939,   949,   955,   958,   964,
-     970,   977,   986,   996,  1004,  1007,  1014,  1018,  1022,  1027,
-    1035,  1038,  1042,  1046,  1055,  1064,  1072,  1082,  1094,  1097,
-    1100,  1106,  1113,  1116,  1122,  1125,  1128,  1134,  1137,  1142,
-    1157,  1161,  1165,  1169,  1173,  1177,  1182,  1187,  1192,  1197,
-    1202,  1207,  1212,  1217,  1222,  1227,  1232,  1237,  1242,  1247,
-    1252,  1257,  1262,  1267,  1272,  1277,  1282,  1286,  1290,  1294,
-    1298,  1302,  1306,  1310,  1314,  1318,  1322,  1326,  1330,  1334,
-    1338,  1342,  1350,  1358,  1362,  1375,  1375,  1378,  1378,  1384,
-    1387,  1403,  1406,  1415,  1419,  1425,  1432,  1447,  1451,  1455,
-    1456,  1462,  1463,  1464,  1465,  1466,  1467,  1468,  1472,  1473,
-    1473,  1473,  1483,  1484,  1488,  1488,  1489,  1489,  1494,  1497,
-    1507,  1510,  1516,  1517,  1521,  1529,  1533,  1540,  1540,  1547,
-    1550,  1557,  1562,  1577,  1577,  1582,  1582,  1589,  1589,  1597,
-    1600,  1606,  1609,  1615,  1619,  1626,  1629,  1632,  1635,  1638,
-    1647,  1651,  1658,  1661,  1667,  1667
+     636,   647,   651,   655,   659,   666,   672,   675,   682,   690,
+     711,   738,   748,   776,   781,   791,   796,   806,   809,   812,
+     815,   821,   828,   831,   835,   839,   844,   849,   856,   860,
+     864,   868,   873,   878,   882,   889,   899,   905,   908,   914,
+     920,   927,   936,   946,   954,   957,   964,   968,   972,   977,
+     985,   988,   992,   996,  1005,  1014,  1022,  1032,  1044,  1047,
+    1050,  1056,  1063,  1066,  1072,  1075,  1078,  1084,  1087,  1092,
+    1107,  1111,  1115,  1119,  1123,  1127,  1132,  1137,  1142,  1147,
+    1152,  1157,  1162,  1167,  1172,  1177,  1182,  1187,  1192,  1197,
+    1202,  1207,  1212,  1217,  1222,  1227,  1232,  1236,  1240,  1244,
+    1248,  1252,  1256,  1260,  1264,  1268,  1272,  1276,  1280,  1284,
+    1288,  1292,  1300,  1308,  1312,  1325,  1325,  1328,  1328,  1334,
+    1337,  1353,  1356,  1365,  1369,  1375,  1382,  1397,  1401,  1405,
+    1406,  1412,  1413,  1414,  1415,  1416,  1417,  1418,  1422,  1423,
+    1423,  1423,  1433,  1434,  1438,  1438,  1439,  1439,  1444,  1447,
+    1457,  1460,  1466,  1467,  1471,  1479,  1483,  1490,  1490,  1497,
+    1500,  1507,  1512,  1527,  1527,  1532,  1532,  1539,  1539,  1547,
+    1550,  1556,  1559,  1565,  1569,  1576,  1579,  1582,  1585,  1588,
+    1597,  1601,  1608,  1611,  1617,  1617
 };
 #endif
 
@@ -3163,57 +3163,7 @@
   case 95:
 
     {
-        //
-        // Multiple declarations of the same function are allowed.
-        //
-        // If this is a definition, the definition production code will check for redefinitions
-        // (we don't know at this point if it's a definition or not).
-        //
-        // Redeclarations are allowed.  But, return types and parameter qualifiers must match.
-        //
-        TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find((yyvsp[-1].interm.function)->getMangledName(), context->getShaderVersion()));
-        if (prevDec) {
-            if (prevDec->getReturnType() != (yyvsp[-1].interm.function)->getReturnType()) {
-                context->error((yylsp[0]), "overloaded functions must have the same return type", (yyvsp[-1].interm.function)->getReturnType().getBasicString());
-                context->recover();
-            }
-            for (size_t i = 0; i < prevDec->getParamCount(); ++i) {
-                if (prevDec->getParam(i).type->getQualifier() != (yyvsp[-1].interm.function)->getParam(i).type->getQualifier()) {
-                    context->error((yylsp[0]), "overloaded functions must have the same parameter qualifiers", (yyvsp[-1].interm.function)->getParam(i).type->getQualifierString());
-                    context->recover();
-                }
-            }
-        }
-
-        //
-        // Check for previously declared variables using the same name.
-        //
-        TSymbol *prevSym = context->symbolTable.find((yyvsp[-1].interm.function)->getName(), context->getShaderVersion());
-        if (prevSym)
-        {
-            if (!prevSym->isFunction())
-            {
-                context->error((yylsp[0]), "redefinition", (yyvsp[-1].interm.function)->getName().c_str(), "function");
-                context->recover();
-            }
-        }
-        else
-        {
-            // Insert the unmangled name to detect potential future redefinition as a variable.
-            TFunction *function = new TFunction(NewPoolTString((yyvsp[-1].interm.function)->getName().c_str()), &(yyvsp[-1].interm.function)->getReturnType());
-            context->symbolTable.getOuterLevel()->insertUnmangled(function);
-        }
-
-        //
-        // If this is a redeclaration, it could also be a definition,
-        // in which case, we want to use the variable names from this one, and not the one that's
-        // being redeclared.  So, pass back up this declaration, not the one in the symbol table.
-        //
-        (yyval.interm).function = (yyvsp[-1].interm.function);
-
-        // We're at the inner scope level of the function's arguments and body statement.
-        // Add the function prototype to the surrounding scope instead.
-        context->symbolTable.getOuterLevel()->insert((yyval.interm).function);
+        (yyval.interm).function = context->parseFunctionDeclarator((yylsp[0]), (yyvsp[-1].interm.function));
     }
 
     break;
@@ -4903,95 +4853,7 @@
   case 274:
 
     {
-        TFunction* function = (yyvsp[0].interm).function;
-        
-        const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName(), context->getShaderVersion());
-        
-        if (builtIn)
-        {
-            context->error((yylsp[0]), "built-in functions cannot be redefined", function->getName().c_str());
-            context->recover();
-        }
-        
-        TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName(), context->getShaderVersion()));
-        //
-        // Note:  'prevDec' could be 'function' if this is the first time we've seen function
-        // as it would have just been put in the symbol table.  Otherwise, we're looking up
-        // an earlier occurance.
-        //
-        if (prevDec->isDefined()) {
-            //
-            // Then this function already has a body.
-            //
-            context->error((yylsp[0]), "function already has a body", function->getName().c_str());
-            context->recover();
-        }
-        prevDec->setDefined();
-        //
-        // Overload the unique ID of the definition to be the same unique ID as the declaration.
-        // Eventually we will probably want to have only a single definition and just swap the
-        // arguments to be the definition's arguments.
-        //
-        function->setUniqueId(prevDec->getUniqueId());
-
-        //
-        // Raise error message if main function takes any parameters or return anything other than void
-        //
-        if (function->getName() == "main") {
-            if (function->getParamCount() > 0) {
-                context->error((yylsp[0]), "function cannot take any parameter(s)", function->getName().c_str());
-                context->recover();
-            }
-            if (function->getReturnType().getBasicType() != EbtVoid) {
-                context->error((yylsp[0]), "", function->getReturnType().getBasicString(), "main function cannot return a value");
-                context->recover();
-            }
-        }
-
-        //
-        // Remember the return type for later checking for RETURN statements.
-        //
-        context->setCurrentFunctionType(&(prevDec->getReturnType()));
-        context->setFunctionReturnsValue(false);
-
-        //
-        // Insert parameters into the symbol table.
-        // If the parameter has no name, it's not an error, just don't insert it
-        // (could be used for unused args).
-        //
-        // Also, accumulate the list of parameters into the HIL, so lower level code
-        // knows where to find parameters.
-        //
-        TIntermAggregate* paramNodes = new TIntermAggregate;
-        for (size_t i = 0; i < function->getParamCount(); i++) {
-            const TConstParameter& param = function->getParam(i);
-            if (param.name != 0) {
-                TVariable *variable = new TVariable(param.name, *param.type);
-                //
-                // Insert the parameters with name in the symbol table.
-                //
-                if (! context->symbolTable.declare(variable)) {
-                    context->error((yylsp[0]), "redefinition", variable->getName().c_str());
-                    context->recover();
-                    delete variable;
-                }
-
-                //
-                // Add the parameter to the HIL
-                //
-                paramNodes = context->intermediate.growAggregate(
-                                               paramNodes,
-                                               context->intermediate.addSymbol(variable->getUniqueId(),
-                                                                       variable->getName(),
-                                                                       variable->getType(), (yylsp[0])),
-                                               (yylsp[0]));
-            } else {
-                paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, (yylsp[0])), (yylsp[0]));
-            }
-        }
-        context->intermediate.setAggregateOperator(paramNodes, EOpParameters, (yylsp[0]));
-        (yyvsp[0].interm).intermAggregate = paramNodes;
-        context->setLoopNestingLevel(0);
+        context->parseFunctionPrototype((yylsp[0]), (yyvsp[0].interm).function, &(yyvsp[0].interm).intermAggregate);
     }
 
     break;