Implemented functionality to collect and return info for attributes and uniforms.
BUG=26
Review URL: http://codereview.appspot.com/2206046

git-svn-id: https://angleproject.googlecode.com/svn/trunk@440 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/VariableInfo.cpp b/src/compiler/VariableInfo.cpp
index f7dd832..5884ede 100644
--- a/src/compiler/VariableInfo.cpp
+++ b/src/compiler/VariableInfo.cpp
@@ -6,6 +6,128 @@
 
 #include "compiler/VariableInfo.h"
 
+static TString arrayBrackets(int index)
+{
+    TStringStream stream;
+    stream << "[" << index << "]";
+    return stream.str();
+}
+
+// Returns the data type for an attribute or uniform.
+static EShDataType getVariableDataType(const TType& type)
+{
+    switch (type.getBasicType()) {
+      case EbtFloat:
+          if (type.isMatrix()) {
+              switch (type.getNominalSize()) {
+                case 2: return SH_FLOAT_MAT2;
+                case 3: return SH_FLOAT_MAT3;
+                case 4: return SH_FLOAT_MAT4;
+                default: UNREACHABLE();
+              }
+          } else if (type.isVector()) {
+              switch (type.getNominalSize()) {
+                case 2: return SH_FLOAT_VEC2;
+                case 3: return SH_FLOAT_VEC3;
+                case 4: return SH_FLOAT_VEC4;
+                default: UNREACHABLE();
+              }
+          } else {
+              return SH_FLOAT;
+          }
+      case EbtInt:
+          if (type.isMatrix()) {
+              UNREACHABLE();
+          } else if (type.isVector()) {
+              switch (type.getNominalSize()) {
+                case 2: return SH_INT_VEC2;
+                case 3: return SH_INT_VEC3;
+                case 4: return SH_INT_VEC4;
+                default: UNREACHABLE();
+              }
+          } else {
+              return SH_INT;
+          }
+      case EbtBool:
+          if (type.isMatrix()) {
+              UNREACHABLE();
+          } else if (type.isVector()) {
+              switch (type.getNominalSize()) {
+                case 2: return SH_BOOL_VEC2;
+                case 3: return SH_BOOL_VEC3;
+                case 4: return SH_BOOL_VEC4;
+                default: UNREACHABLE();
+              }
+          } else {
+              return SH_BOOL;
+          }
+      case EbtSampler2D: return SH_SAMPLER_2D;
+      case EbtSamplerCube: return SH_SAMPLER_CUBE;
+      default: UNREACHABLE();
+    }
+    return SH_NONE;
+}
+
+static void getBuiltInVariableInfo(const TType& type,
+                                   const TString& name,
+                                   TVariableInfoList& infoList);
+static void getUserDefinedVariableInfo(const TType& type,
+                                       const TString& name,
+                                       TVariableInfoList& infoList);
+
+// Returns info for an attribute or uniform.
+static void getVariableInfo(const TType& type,
+                            const TString& name,
+                            TVariableInfoList& infoList)
+{
+    if (type.getBasicType() == EbtStruct) {
+        if (type.isArray()) {
+            for (int i = 0; i < type.getArraySize(); ++i) {
+                TString lname = name + arrayBrackets(i);
+                getUserDefinedVariableInfo(type, lname, infoList);
+            }
+        } else {
+            getUserDefinedVariableInfo(type, name, infoList);
+        }
+    } else {
+        getBuiltInVariableInfo(type, name, infoList);
+    }
+}
+
+void getBuiltInVariableInfo(const TType& type,
+                            const TString& name,
+                            TVariableInfoList& infoList)
+{
+    ASSERT(type.getBasicType() != EbtStruct);
+
+    TVariableInfo varInfo;
+    if (type.isArray()) {
+        varInfo.name = (name + "[0]").c_str();
+        varInfo.size = type.getArraySize();
+    } else {
+        varInfo.name = name.c_str();
+        varInfo.size = 1;
+    }
+    varInfo.type = getVariableDataType(type);
+    infoList.push_back(varInfo);
+}
+
+void getUserDefinedVariableInfo(const TType& type,
+                                const TString& name,
+                                TVariableInfoList& infoList)
+{
+    ASSERT(type.getBasicType() == EbtStruct);
+
+    TString lname = name + ".";
+    const TTypeList* structure = type.getStruct();
+    for (size_t i = 0; i < structure->size(); ++i) {
+        const TType* fieldType = (*structure)[i].type;
+        getVariableInfo(*fieldType,
+                        lname + fieldType->getFieldName(),
+                        infoList);
+    }
+}
+
 CollectAttribsUniforms::CollectAttribsUniforms(TVariableInfoList& attribs,
                                                TVariableInfoList& uniforms)
     : mAttribs(attribs),
@@ -13,7 +135,7 @@
 {
 }
 
-// TODO(alokp): Implement these functions.
+// We are only interested in attribute and uniform variable declaration.
 void CollectAttribsUniforms::visitSymbol(TIntermSymbol*)
 {
 }
@@ -22,32 +144,62 @@
 {
 }
 
-bool CollectAttribsUniforms::visitBinary(Visit visit, TIntermBinary*)
+bool CollectAttribsUniforms::visitBinary(Visit, TIntermBinary*)
 {
     return false;
 }
 
-bool CollectAttribsUniforms::visitUnary(Visit visit, TIntermUnary*)
+bool CollectAttribsUniforms::visitUnary(Visit, TIntermUnary*)
 {
     return false;
 }
 
-bool CollectAttribsUniforms::visitSelection(Visit visit, TIntermSelection*)
+bool CollectAttribsUniforms::visitSelection(Visit, TIntermSelection*)
 {
     return false;
 }
 
-bool CollectAttribsUniforms::visitAggregate(Visit visit, TIntermAggregate*)
+bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
+{
+    bool visitChildren = false;
+
+    switch (node->getOp())
+    {
+    case EOpSequence:
+        // We need to visit sequence children to get to variable declarations.
+        visitChildren = true;
+        break;
+    case EOpDeclaration: {
+        const TIntermSequence& sequence = node->getSequence();
+        const TIntermSymbol* variable = sequence.front()->getAsSymbolNode();
+        const TType& type = variable->getType();
+        TQualifier qualifier = type.getQualifier();
+        if (qualifier == EvqAttribute || qualifier == EvqUniform)
+        {
+            TVariableInfoList& infoList = qualifier == EvqAttribute ?
+                mAttribs : mUniforms;
+            for (TIntermSequence::const_iterator i = sequence.begin();
+                 i != sequence.end(); ++i)
+            {
+                variable = (*i)->getAsSymbolNode();
+                getVariableInfo(variable->getType(), variable->getSymbol(),
+                                infoList);
+            }
+        }
+        break;
+    }
+    default: break;
+    }
+
+    return visitChildren;
+}
+
+bool CollectAttribsUniforms::visitLoop(Visit, TIntermLoop*)
 {
     return false;
 }
 
-bool CollectAttribsUniforms::visitLoop(Visit visit, TIntermLoop*)
-{
-    return false;
-}
-
-bool CollectAttribsUniforms::visitBranch(Visit visit, TIntermBranch*)
+bool CollectAttribsUniforms::visitBranch(Visit, TIntermBranch*)
 {
     return false;
 }