Implement the full scheme for ES precision qualifiers, generalizing existing storage...
authorJohn Kessenich <cepheus@frii.com>
Thu, 24 Jan 2013 23:10:51 +0000 (23:10 +0000)
committerJohn Kessenich <cepheus@frii.com>
Thu, 24 Jan 2013 23:10:51 +0000 (23:10 +0000)
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@20317 e7fa87d3-cd2b-0410-9028-fcbf551c1848

15 files changed:
glslang/Include/BaseTypes.h
glslang/Include/Types.h
glslang/Include/intermediate.h
glslang/MachineIndependent/Intermediate.cpp
glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/ParseHelper.h
glslang/MachineIndependent/QualifierAlive.cpp
glslang/MachineIndependent/QualifierAlive.h
glslang/MachineIndependent/ShaderLang.cpp
glslang/MachineIndependent/SymbolTable.cpp
glslang/MachineIndependent/SymbolTable.h
glslang/MachineIndependent/glslang.l
glslang/MachineIndependent/glslang.y
glslang/MachineIndependent/intermOut.cpp
glslang/MachineIndependent/parseConst.cpp

index 1283c0c..b758494 100644 (file)
@@ -55,7 +55,7 @@ enum TBasicType {
     EbtSamplerRectShadow,  // ARB_texture_rectangle
     EbtGuardSamplerEnd,    // non type:  see implementation of IsSampler()
     EbtStruct,
-    EbtAddress,            // should be deprecated??
+    EbtNumTypes
 };
 
 __inline bool IsSampler(TBasicType type)
@@ -69,7 +69,7 @@ __inline bool IsSampler(TBasicType type)
 // to allocate variables in.  Since built-ins tend to go to different registers
 // than varying or uniform, it makes sense they are peers, not sub-classes.
 //
-enum TQualifier {
+enum TStorageQualifier {
     EvqTemporary,     // For temporaries (within a function), read/write
     EvqGlobal,        // For globals read/write
     EvqConst,         // User defined constants and non-output parameters in functions
@@ -104,7 +104,7 @@ enum TQualifier {
 //
 // This is just for debug print out, carried along with the definitions above.
 //
-__inline const char* getQualifierString(TQualifier q) 
+__inline const char* getStorageQualifierString(TStorageQualifier q) 
 {
     switch (q) {
     case EvqTemporary:      return "Temporary";      break;
@@ -129,4 +129,22 @@ __inline const char* getQualifierString(TQualifier q)
     }
 }
 
+enum TPrecisionQualifier {
+    EpqNone,
+    EpqLow,
+    EpqMedium,
+    EpqHigh
+};
+
+__inline const char* getPrecisionQualifierString(TPrecisionQualifier p)
+{
+    switch(p) {
+    case EpqNone:   return "";        break;
+    case EpqLow:    return "lowp";    break;
+    case EpqMedium: return "mediump"; break;
+    case EpqHigh:   return "highp";   break;
+    default:        return "unknown precision qualifier";
+    }
+}
+
 #endif // _BASICTYPES_INCLUDED_
index e9bfa44..a755cd0 100644 (file)
@@ -56,13 +56,20 @@ inline TTypeList* NewPoolTTypeList()
 
 //
 // This is a workaround for a problem with the yacc stack,  It can't have
-// types that it thinks have non-trivial constructors.  It should 
+// types that it thinks have non-trivial constructors.  It should
 // just be used while recognizing the grammar, not anything else.  Pointers
 // could be used, but also trying to avoid lots of memory management overhead.
 //
 // Not as bad as it looks, there is no actual assumption that the fields
 // match up or are name the same or anything like that.
 //
+
+class TQualifier {
+public:
+       TStorageQualifier storage     : 7;
+    TPrecisionQualifier precision : 3;
+};
+
 class TPublicType {
 public:
     TBasicType type;
@@ -74,10 +81,9 @@ public:
     TType* userDef;
     int line;
 
-    void setBasic(TBasicType bt, TQualifier q, int ln = 0) 
-    { 
-        type = bt;
-        qualifier = q;
+    void initType(int ln = 0)
+    {
+        type = EbtVoid;
         size = 1;
         matrix = false;
         array = false;
@@ -86,6 +92,18 @@ public:
         line = ln;
     }
 
+    void initQualifiers(bool global = false)
+    {
+        qualifier.storage = global ? EvqGlobal : EvqTemporary;
+        qualifier.precision = EpqNone;
+    }
+
+    void init(int line = 0, bool global = false)
+    {
+        initType(line);
+        initQualifiers(global);
+    }
+
     void setAggregate(int s, bool m = false)
     {
         size = s;
@@ -107,22 +125,28 @@ typedef std::map<TTypeList*, TTypeList*>::iterator TStructureMapIterator;
 class TType {
 public:
     POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
-    explicit TType(TBasicType t, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) :
-                            type(t), qualifier(q), size(s), matrix(m), array(a), arraySize(0),
-                            structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0)
-                            { }
+    explicit TType(TBasicType t, TStorageQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) :
+                            type(t), size(s), matrix(m), array(a), arraySize(0),
+                            structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0),
+                            fieldName(0), mangled(0), typeName(0) {
+                                qualifier.storage = q;
+                                qualifier.precision = EpqNone;
+                            }
     explicit TType(const TPublicType &p) :
-                            type(p.type), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), 
+                            type(p.type), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize),
                             structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0)
                             {
-                              if (p.userDef) {
-                                  structure = p.userDef->getStruct();
-                                  typeName = NewPoolTString(p.userDef->getTypeName().c_str());
-                              }
+                                qualifier = p.qualifier;
+                                if (p.userDef) {
+                                    structure = p.userDef->getStruct();
+                                    typeName = NewPoolTString(p.userDef->getTypeName().c_str());
+                                }
                             }
     explicit TType(TTypeList* userDef, const TString& n) :
-                            type(EbtStruct), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),
+                            type(EbtStruct), size(1), matrix(false), array(false), arraySize(0),
                             structure(userDef), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0) {
+                                qualifier.storage = EvqTemporary;
+                                qualifier.precision = EpqNone;
                                                                typeName = NewPoolTString(n.c_str());
                             }
        explicit TType() {}
@@ -180,47 +204,47 @@ public:
 
                return newType;
        }
-    
+
     virtual void setType(TBasicType t, int s, bool m, bool a, int aS = 0)
                             { type = t; size = s; matrix = m; array = a; arraySize = aS; }
     virtual void setType(TBasicType t, int s, bool m, TType* userDef = 0)
-                            { type = t; 
-                              size = s; 
-                              matrix = m; 
+                            { type = t;
+                              size = s;
+                              matrix = m;
                               if (userDef)
-                                  structure = userDef->getStruct(); 
+                                  structure = userDef->getStruct();
                               // leave array information intact.
                             }
     virtual void setTypeName(const TString& n) { typeName = NewPoolTString(n.c_str()); }
     virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); }
     virtual const TString& getTypeName() const
-    { 
+    {
                assert(typeName);               
-       return *typeName; 
+       return *typeName;
     }
 
     virtual const TString& getFieldName() const
-    { 
+    {
        assert(fieldName);
-               return *fieldName; 
+               return *fieldName;
     }
-    
+
     virtual TBasicType getBasicType() const { return type; }
-    virtual TQualifier getQualifier() const { return qualifier; }
-    virtual void changeQualifier(TQualifier q) { qualifier = q; }
+    virtual TQualifier& getQualifier() { return qualifier; }
+    virtual const TQualifier& getQualifier() const { return qualifier; }
 
     // One-dimensional size of single instance type
-    virtual int getNominalSize() const { return size; }  
-    
+    virtual int getNominalSize() const { return size; }
+
     // Full-dimensional size of single instance of type
-    virtual int getInstanceSize() const  
+    virtual int getInstanceSize() const
     {
         if (matrix)
             return size * size;
         else
             return size;
     }
-    
+
        virtual bool isMatrix() const { return matrix ? true : false; }
     virtual bool isArray() const  { return array ? true : false; }
     int getArraySize() const { return arraySize; }
@@ -251,18 +275,19 @@ public:
         }
     }
     const char* getBasicString() const { return TType::getBasicString(type); }
-    const char* getQualifierString() const { return ::getQualifierString(qualifier); }
+    const char* getStorageQualifierString() const { return ::getStorageQualifierString(qualifier.storage); }
+    const char* getPrecisionQualifierString() const { return ::getPrecisionQualifierString(qualifier.precision); }
     TTypeList* getStruct() { return structure; }
 
     int getObjectSize() const
     {
         int totalSize;
-        
+
         if (getBasicType() == EbtStruct)
             totalSize = getStructSize();
         else if (matrix)
-            totalSize = size * size;            
-        else 
+            totalSize = size * size;
+        else
             totalSize = size;
 
         if (isArray())
@@ -275,10 +300,10 @@ public:
     TString& getMangledName() {
         if (!mangled) {
                        mangled = NewPoolTString("");
-            buildMangledName(*mangled);            
+            buildMangledName(*mangled);
             *mangled += ';' ;
         }
-    
+
         return *mangled;
     }
     bool sameElementType(const TType& right) const {
@@ -299,16 +324,17 @@ public:
         return !operator==(right);
     }
     TString getCompleteString() const;
-        
+
 protected:
     void buildMangledName(TString&);
     int getStructSize() const;
 
-       TBasicType type      : 6;
-       TQualifier qualifier : 7;
+       TBasicType type      : 8;
        int size             : 8; // size of vector or matrix, not size of array
        unsigned int matrix  : 1;
        unsigned int array   : 1;
+    TQualifier qualifier;
+
     int arraySize;
 
     TTypeList* structure;      // 0 unless this is a struct
index 0def51d..cbab65d 100644 (file)
@@ -285,14 +285,14 @@ public:
     virtual TType* getTypePointer() { return &type; }
     
     virtual TBasicType getBasicType() const { return type.getBasicType(); }
-    virtual TQualifier getQualifier() const { return type.getQualifier(); }
+    virtual TQualifier& getQualifier() { return type.getQualifier(); }
     virtual int getNominalSize() const { return type.getNominalSize(); }
     virtual int getSize() const { return type.getInstanceSize(); }
     virtual bool isMatrix() const { return type.isMatrix(); }
     virtual bool isArray()  const { return type.isArray(); }
     virtual bool isVector() const { return type.isVector(); }
     const char* getBasicString()      const { return type.getBasicString(); }
-    const char* getQualifierString()  const { return type.getQualifierString(); }
+    const char* getStorageQualifierString()  const { return type.getStorageQualifierString(); }
     TString getCompleteString() const { return type.getCompleteString(); }
 
 protected:
@@ -451,7 +451,7 @@ public:
     virtual void traverse(TIntermTraverser*);
     virtual void setUserDefined() { userDefined = true; }
     virtual bool isUserDefined() { return userDefined; }
-    virtual TQualifierList& getQualifier() { return qualifier; }
+    virtual TQualifierList& getQualifierList() { return qualifier; }
        void setOptimize(bool o) { optimize = o; }
        void setDebug(bool d) { debug = d; }
        bool getOptimize() { return optimize; }
index 117ce95..040de59 100644 (file)
@@ -546,13 +546,14 @@ TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nod
 
 TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
 {
-    if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
+    if (left->getType().getQualifier().storage == EvqConst && 
+        right->getType().getQualifier().storage == EvqConst) {
         return right;
     } else {
         TIntermTyped *commaAggregate = growAggregate(left, right, line);
         commaAggregate->getAsAggregate()->setOperator(EOpComma);    
         commaAggregate->setType(right->getType());
-        commaAggregate->getTypePointer()->changeQualifier(EvqTemporary);
+        commaAggregate->getTypePointer()->getQualifier().storage = EvqTemporary;
         return commaAggregate;
     }
 }
@@ -830,7 +831,11 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
     // operand.  Then only deviations from this need be coded.
     //
     setType(left->getType());
-    type.changeQualifier(EvqTemporary);
+    type.getQualifier().storage = EvqTemporary;
+
+    // Fix precision qualifiers
+    if (right->getQualifier().precision > getQualifier().precision)
+        getQualifier().precision = right->getQualifier().precision;
 
     //
     // Array operations.
@@ -1510,7 +1515,8 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
     
     const TType& t = node->getType();
     
-    return addConstantUnion(leftUnionArray, TType(promoteTo, t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine());
+    return addConstantUnion(leftUnionArray, TType(promoteTo, t.getQualifier().storage, t.getNominalSize(), t.isMatrix(), 
+                            t.isArray()), node->getLine());
 }
 
 void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
index 7d7f46b..797ec25 100644 (file)
 //
 ////////////////////////////////////////////////////////////////////////
 
+
+TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage L, TInfoSink& is) : 
+            intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0),
+            recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0),
+            switchNestingLevel(0), inTypeParen(false), 
+            version(110), profile(ENoProfile), futureCompatibility(false),
+            contextPragma(true, false)
+{
+    // Default precisions for version 110, to be overridden for 
+    // other versions/profiles/stage combinations
+    for (int type = 0; type < EbtNumTypes; ++type)
+        defaultPrecision[type] = EpqHigh;
+    
+    defaultPrecision[EbtVoid]   = EpqNone;
+    defaultPrecision[EbtDouble] = EpqNone;
+    defaultPrecision[EbtBool]   = EpqNone;
+    defaultPrecision[EbtVoid]   = EpqNone;
+}
+
 //
 // Look at a '.' field selector string and change it into offsets
 // for a vector.
@@ -331,7 +350,7 @@ bool TParseContext::lValueErrorCheck(int line, char* op, TIntermTyped* node)
         symbol = symNode->getSymbol().c_str();
 
     char* message = 0;
-    switch (node->getQualifier()) {
+    switch (node->getQualifier().storage) {
     case EvqConst:          message = "can't modify a const";        break;
     case EvqConstReadOnly:  message = "can't modify a const";        break;
     case EvqAttribute:      message = "can't modify an attribute";   break;
@@ -395,7 +414,7 @@ bool TParseContext::lValueErrorCheck(int line, char* op, TIntermTyped* node)
 //
 bool TParseContext::constErrorCheck(TIntermTyped* node)
 {
-    if (node->getQualifier() == EvqConst)
+    if (node->getQualifier().storage == EvqConst)
         return false;
 
     error(node->getLine(), "constant expression required", "", "");
@@ -503,14 +522,14 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction
             overFull = true;
         if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
             full = true;
-        if (function[i].type->getQualifier() != EvqConst)
+        if (function[i].type->getQualifier().storage != EvqConst)
             constType = false;
         if (function[i].type->isArray())
             arrayArg = true;
     }
     
     if (constType)
-        type->changeQualifier(EvqConst);
+        type->getQualifier().storage = EvqConst;
 
     if (type->isArray() && type->getArraySize() != function.getParamCount()) {
         error(line, "array constructor needs one argument per array element", "constructor", "");
@@ -623,19 +642,19 @@ bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const
 
 bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualifier)
 {
-    switch (qualifier) {
+    switch (qualifier.storage) {
     case EvqIn:
         profileRequires(line, ENoProfile, 130, 0, "in for stage inputs");
         profileRequires(line, EEsProfile, 300, 0, "in for stage inputs");
-        qualifier = EvqVaryingIn;
+        qualifier.storage = EvqVaryingIn;
         break;
     case EvqOut:
         profileRequires(line, ENoProfile, 130, 0, "out for stage outputs");
         profileRequires(line, EEsProfile, 300, 0, "out for stage outputs");
-        qualifier = EvqVaryingOut;
+        qualifier.storage = EvqVaryingOut;
         break;
     case EvqInOut:
-        qualifier = EvqVaryingIn;
+        qualifier.storage = EvqVaryingIn;
         error(line, "cannot use 'inout' at global scope", "", "");
 
         return true;
@@ -646,20 +665,34 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif
 
 bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType)
 {
-    if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) &&
+    if ((pType.qualifier.storage == EvqVaryingIn || 
+         pType.qualifier.storage == EvqVaryingOut || 
+         pType.qualifier.storage == EvqAttribute) &&
         pType.type == EbtStruct) {
-        error(line, "cannot be used with a structure", getQualifierString(pType.qualifier), "");
+
+        error(line, "cannot be used with a structure", getStorageQualifierString(pType.qualifier.storage), "");
         
         return true;
     }
 
-    if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
+    if (pType.qualifier.storage != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
         return true;
 
     return false;
 }
 
-bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type)
+void TParseContext::setDefaultPrecision(int line, TBasicType type, TPrecisionQualifier qualifier)
+{
+    // TODO: push and pop for nested scopes
+    if (IsSampler(type) || type == EbtInt || type == EbtFloat) {
+        defaultPrecision[type] = qualifier;
+    } else {
+        error(line, "cannot apply precision statement to this type", TType::getBasicString(type), "");
+        recover();
+    }
+}
+
+bool TParseContext::parameterSamplerErrorCheck(int line, TStorageQualifier qualifier, const TType& type)
 {
     if ((qualifier == EvqOut || qualifier == EvqInOut) && 
              type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
@@ -741,12 +774,12 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
 //
 bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
 {
-    if (type.qualifier == EvqAttribute) {
+    if (type.qualifier.storage == EvqAttribute) {
         error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str(), "");
         return true;
     }
 
-    if (type.qualifier == EvqConst)
+    if (type.qualifier.storage == EvqConst)
         profileRequires(line, ENoProfile, 120, "GL_3DL_array_objects", "const array");
 
     return false;
@@ -899,8 +932,8 @@ bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPubli
     //
     // Make the qualifier make sense.
     //
-    if (type.qualifier == EvqConst) {
-        type.qualifier = EvqTemporary;
+    if (type.qualifier.storage  == EvqConst) {
+        type.qualifier.storage = EvqTemporary;
         error(line, "variables with qualifier 'const' must be initialized", identifier.c_str(), "");
         return true;
     }
@@ -933,24 +966,24 @@ bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType
     return false;
 }
 
-bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TType* type)
+bool TParseContext::paramErrorCheck(int line, TStorageQualifier qualifier, TType* type)
 {
     switch (qualifier) {
     case EvqConst:
     case EvqConstReadOnly:
-        type->changeQualifier(EvqConstReadOnly);
+        type->getQualifier().storage = EvqConstReadOnly;
         return false;
     case EvqIn:
     case EvqOut:
     case EvqInOut:
-        type->changeQualifier(qualifier);
+        type->getQualifier().storage = qualifier;
         return false;
     case EvqTemporary:
-        type->changeQualifier(EvqIn);
+        type->getQualifier().storage = EvqIn;
         return false;
     default:
-        type->changeQualifier(EvqIn);
-        error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier), "");
+        type->getQualifier().storage = EvqIn;
+        error(line, "qualifier not allowed on function parameter", getStorageQualifierString(qualifier), "");
         return true;
     }
 }
@@ -1016,9 +1049,9 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu
     //
     // identifier must be of type constant, a global, or a temporary
     //
-    TQualifier qualifier = variable->getType().getQualifier();
+    TStorageQualifier qualifier = variable->getType().getQualifier().storage;
     if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) {
-        error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString(), "");
+        error(line, " cannot initialize this type of qualifier ", variable->getType().getStorageQualifierString(), "");
         return true;
     }
     //
@@ -1026,15 +1059,15 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu
     //
 
     if (qualifier == EvqConst) {
-        if (qualifier != initializer->getType().getQualifier()) {
+        if (qualifier != initializer->getType().getQualifier().storage) {
             error(line, " assigning non-constant to", "=", "'%s'", variable->getType().getCompleteString().c_str());
-            variable->getType().changeQualifier(EvqTemporary);
+            variable->getType().getQualifier().storage = EvqTemporary;
             return true;
         }
         if (type != initializer->getType()) {
             error(line, " non-matching types for const initializer ", 
-                variable->getType().getQualifierString(), "");
-            variable->getType().changeQualifier(EvqTemporary);
+                variable->getType().getStorageQualifierString(), "");
+            variable->getType().getQualifier().storage = EvqTemporary;
             return true;
         }
         if (initializer->getAsConstantUnion()) { 
@@ -1053,7 +1086,7 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu
             variable->shareConstPointer(constArray);
         } else {
             error(line, " cannot assign to", "=", "'%s'", variable->getType().getCompleteString().c_str());
-            variable->getType().changeQualifier(EvqTemporary);
+            variable->getType().getQualifier().storage = EvqTemporary;
             return true;
         }
     }
index 3e1a125..2c28cce 100644 (file)
@@ -45,7 +45,7 @@ struct TMatrixFields {
     bool wholeRow;
     bool wholeCol;
     int row;
-    int col;    
+    int col;
 };
 
 typedef enum {
@@ -67,12 +67,7 @@ struct TPragma {
 // they can be passed to the parser without needing a global.
 //
 struct TParseContext {
-    TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage L, TInfoSink& is) : 
-            intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0),
-            recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0),
-            switchNestingLevel(0), inTypeParen(false), 
-            version(110), profile(ENoProfile), futureCompatibility(false),
-            contextPragma(true, false) {  }
+    TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage L, TInfoSink& is);
     TIntermediate& intermediate; // to hold and build a parse tree
     TSymbolTable& symbolTable;   // symbol table that goes with the language currently being parsed
     TInfoSink& infoSink;
@@ -91,18 +86,19 @@ struct TParseContext {
     EProfile profile;            // the declared profile in the shader (core by default)
     bool futureCompatibility;    // true if requesting errors for future compatibility (false by default)
     TMap<TString, TBehavior> extensionBehavior;    // for each extension string, what it's current enablement is
-    
+
     struct TPragma contextPragma;
-       TString HashErrMsg; 
+    TPrecisionQualifier defaultPrecision[EbtNumTypes];
+       TString HashErrMsg;
     bool AfterEOF;
 
     void initializeExtensionBehavior();
 
-    void C_DECL error(TSourceLoc, const char *szReason, const char *szToken, 
+    void C_DECL error(TSourceLoc, const char *szReason, const char *szToken,
                       const char *szExtraInfoFormat, ...);
     bool reservedErrorCheck(int line, const TString& identifier);
     void recover();
-    
+
     bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line);
     bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, int line);
     void assignError(int line, const char* op, TString left, TString right);
@@ -125,13 +121,14 @@ struct TParseContext {
     bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
     bool globalQualifierFixAndErrorCheck(int line, TQualifier&);
     bool structQualifierErrorCheck(int line, const TPublicType& pType);
-    bool parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type);
+    void setDefaultPrecision(int line, TBasicType, TPrecisionQualifier);
+    bool parameterSamplerErrorCheck(int line, TStorageQualifier qualifier, const TType& type);
     bool containsSampler(TType& type);
     bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type);
     bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type);
-    bool paramErrorCheck(int line, TQualifier qualifier, TType* type);
+    bool paramErrorCheck(int line, TStorageQualifier qualifier, TType* type);
     const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0);
-    bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, 
+    bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
                             TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
     bool areAllChildConst(TIntermAggregate* aggrNode);
     TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc);
index a88fd43..e45138b 100644 (file)
@@ -36,7 +36,7 @@
 
 class TAliveTraverser : public TIntermTraverser {
 public:
-    TAliveTraverser(TQualifier q) : TIntermTraverser(), found(false), qualifier(q)
+    TAliveTraverser(TStorageQualifier q) : TIntermTraverser(), found(false), qualifier(q)
     {
         visitSymbol    = AliveSymbol;
         visitSelection = AliveSelection;
@@ -45,7 +45,7 @@ public:
     bool wasFound() { return found; }
 protected:
     bool found;
-    TQualifier qualifier;
+    TStorageQualifier qualifier;
 
     friend void AliveSymbol(TIntermSymbol*, TIntermTraverser*);
     friend bool AliveSelection(bool, TIntermSelection*, TIntermTraverser*);
@@ -59,7 +59,7 @@ protected:
 // ?? It does not do this well yet, this is just a place holder
 // that simply determines if it was reference at all, anywhere.
 //
-bool QualifierWritten(TIntermNode* node, TQualifier qualifier)
+bool QualifierWritten(TIntermNode* node, TStorageQualifier qualifier)
 {
     TAliveTraverser it(qualifier);
 
@@ -76,7 +76,7 @@ void AliveSymbol(TIntermSymbol* node, TIntermTraverser* it)
     //
     // If it's what we're looking for, record it.
     //
-    if (node->getQualifier() == lit->qualifier)
+    if (node->getQualifier().storage == lit->qualifier)
         lit->found = true;
 }
 
index 60dfa50..eb777e2 100644 (file)
@@ -32,4 +32,4 @@
 //POSSIBILITY OF SUCH DAMAGE.
 //
 
-bool QualifierWritten(TIntermNode* root, TQualifier);
+bool QualifierWritten(TIntermNode* root, TStorageQualifier);
index f38f856..57b1362 100644 (file)
@@ -92,12 +92,11 @@ int ShInitialize()
 
         SetGlobalPoolAllocatorPtr(gPoolAllocator);
 
-        symTables[EShLangVertex].pop();
-        symTables[EShLangFragment].pop();
+        symTables[EShLangVertex].pop(0);
+        symTables[EShLangFragment].pop(0);
 
         builtInPoolAllocator->popAll();
-        delete builtInPoolAllocator;        
-
+        delete builtInPoolAllocator;
     }
 
     return ret ? 1 : 0;
@@ -343,7 +342,7 @@ int ShCompile(
     // throwing away all but the built-ins.
     //
     while (! symbolTable.atSharedBuiltInLevel())
-        symbolTable.pop();
+        symbolTable.pop(0);
 
     FinalizePreprocessor();
     //
index 60f31b2..2983cde 100644 (file)
@@ -111,7 +111,7 @@ int TType::getStructSize() const
 
 void TVariable::dump(TInfoSink& infoSink) const 
 {
-    infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getBasicString();
+    infoSink.debug << getName().c_str() << ": " << type.getStorageQualifierString() << " " << type.getBasicString();
     if (type.isArray()) {
         infoSink.debug << "[0]";
     }
@@ -154,6 +154,8 @@ TSymbolTableLevel::~TSymbolTableLevel()
 {
        for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
                delete (*it).second;
+
+    delete [] defaultPrecision;
 }
 
 //
index 5876a4d..55603fd 100644 (file)
@@ -46,7 +46,7 @@
 //   so that symbol table lookups are never ambiguous.  This allows
 //   a simpler symbol table structure.
 //
-// * Pushing and popping of scope, so symbol table will really be a stack 
+// * Pushing and popping of scope, so symbol table will really be a stack
 //   of symbol tables.  Searched from the top, with new inserts going into
 //   the top.
 //
 #include "../Include/Common.h"
 #include "../Include/intermediate.h"
 #include "../Include/InfoSink.h"
+
 //
 // Symbol base class.  (Can build functions or variables out of these...)
 //
-class TSymbol {    
+class TSymbol {
 public:
     POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
     TSymbol(const TString *n) :  name(n) { }
@@ -87,29 +87,29 @@ protected:
 
 //
 // Variable class, meaning a symbol that's not a function.
-// 
+//
 // There could be a separate class heirarchy for Constant variables;
 // Only one of int, bool, or float, (or none) is correct for
 // any particular use, but it's easy to do this way, and doesn't
 // seem worth having separate classes, and "getConst" can't simply return
-// different values for different types polymorphically, so this is 
+// different values for different types polymorphically, so this is
 // just simple and pragmatic.
 //
 class TVariable : public TSymbol {
 public:
     TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { }
     virtual ~TVariable() { }
-    virtual bool isVariable() const { return true; }    
-    TType& getType() { return type; }    
+    virtual bool isVariable() const { return true; }
+    TType& getType() { return type; }
     const TType& getType() const { return type; }
     bool isUserType() const { return userType; }
-    void changeQualifier(TQualifier qualifier) { type.changeQualifier(qualifier); }
+    void setStorageQualifier(TStorageQualifier qualifier) { type.getQualifier().storage = qualifier; }
     void updateArrayInformationType(TType *t) { arrayInformationType = t; }
     TType* getArrayInformationType() { return arrayInformationType; }
 
     virtual void dump(TInfoSink &infoSink) const;
 
-    constUnion* getConstPointer() { 
+    constUnion* getConstPointer() {
         if (!unionArray)
             unionArray = new constUnion[type.getObjectSize()];
 
@@ -121,11 +121,11 @@ public:
     void shareConstPointer( constUnion *constArray)
     {
         delete unionArray;
-        unionArray = constArray;  
+        unionArray = constArray;
     }
        TVariable(const TVariable&, TStructureMap& remapper); // copy constructor
        virtual TVariable* clone(TStructureMap& remapper);
-      
+
 protected:
     TType type;
     bool userType;
@@ -149,7 +149,7 @@ struct TParameter {
 };
 
 //
-// The function sub-class of a symbol.  
+// The function sub-class of a symbol.
 //
 class TFunction : public TSymbol {
 public:
@@ -158,21 +158,21 @@ public:
         returnType(TType(EbtVoid)),
         op(o),
         defined(false) { }
-    TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) : 
-        TSymbol(name), 
+    TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) :
+        TSymbol(name),
         returnType(retType),
         mangledName(*name + '('),
         op(tOp),
         defined(false) { }
        virtual ~TFunction();
-    virtual bool isFunction() const { return true; }    
-    
-    void addParameter(TParameter& p) 
-    { 
+    virtual bool isFunction() const { return true; }
+
+    void addParameter(TParameter& p)
+    {
         parameters.push_back(p);
         mangledName = mangledName + p.type->getMangledName();
     }
-    
+
     const TString& getMangledName() const { return mangledName; }
     const TType& getReturnType() const { return returnType; }
     void relateToOperator(TOperator o) { op = o; }
@@ -180,14 +180,14 @@ public:
     void setDefined() { defined = true; }
     bool isDefined() { return defined; }
 
-    int getParamCount() const { return static_cast<int>(parameters.size()); }    
+    int getParamCount() const { return static_cast<int>(parameters.size()); }
           TParameter& operator [](int i)       { return parameters[i]; }
     const TParameter& operator [](int i) const { return parameters[i]; }
-    
+
     virtual void dump(TInfoSink &infoSink) const;
        TFunction(const TFunction&, TStructureMap& remapper);
        virtual TFunction* clone(TStructureMap& remapper);
-    
+
 protected:
     typedef TVector<TParameter> TParamList;
        TParamList parameters;
@@ -201,17 +201,17 @@ protected:
 class TSymbolTableLevel {
 public:
     POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
-    TSymbolTableLevel() { }
+    TSymbolTableLevel() : defaultPrecision (0) { }
        ~TSymbolTableLevel();
-    
-    bool insert(TSymbol& symbol) 
+
+    bool insert(TSymbol& symbol)
     {
         //
         // returning true means symbol was added to the table
         //
         tInsertResult result;
         result = level.insert(tLevelPair(symbol.getMangledName(), &symbol));
-        
+
         return result.second;
     }
 
@@ -224,17 +224,44 @@ public:
             return (*it).second;
     }
 
+    // Use this to do a lazy 'push' of precision defaults the first time
+    // a precision statement is seen in a new scope.  Leave it at 0 for
+    // when no push was needed.  Thus, it is not the current defaults,
+    // it is what to restore the defaults to when popping a level.
+    void setPreviousDefaultPrecisions(const TPrecisionQualifier *p)
+    {
+        // can call multiple times at one scope, will only latch on first call,
+        // as we're tracking the previous scope's values, not the current values
+        if (defaultPrecision != 0)
+            return;
+
+        defaultPrecision = new TPrecisionQualifier[EbtNumTypes];
+        for (int t = 0; t < EbtNumTypes; ++t)
+            defaultPrecision[t] = p[t];
+    }
+
+    void getPreviousDefaultPrecisions(TPrecisionQualifier *p)
+    {
+        // can be called for table level pops that didn't set the
+        // defaults
+        if (defaultPrecision == 0 || p == 0)
+            return;
+
+        for (int t = 0; t < EbtNumTypes; ++t)
+            p[t] = defaultPrecision[t];
+    }
 
     void relateToOperator(const char* name, TOperator op);
     void dump(TInfoSink &infoSink) const;
        TSymbolTableLevel* clone(TStructureMap& remapper);
-    
+
 protected:
     typedef std::map<TString, TSymbol*, std::less<TString>, pool_allocator<std::pair<const TString, TSymbol*> > > tLevel;
     typedef const tLevel::value_type tLevelPair;
     typedef std::pair<tLevel::iterator, bool> tInsertResult;
 
     tLevel level;
+    TPrecisionQualifier *defaultPrecision;
 };
 
 class TSymbolTable {
@@ -258,7 +285,7 @@ public:
     {
         // level 0 is always built In symbols, so we never pop that out
         while (table.size() > 1)
-            pop();
+            pop(0);
     }
 
     //
@@ -270,13 +297,17 @@ public:
     bool atBuiltInLevel() { return atSharedBuiltInLevel() || atDynamicBuiltInLevel(); }
     bool atSharedBuiltInLevel() { return table.size() == 1; }  
     bool atGlobalLevel() { return table.size() <= 3; }
-    void push() { 
+    
+    void push()
+    {
         table.push_back(new TSymbolTableLevel);
     }
 
-    void pop() { 
-        delete table[currentLevel()]; 
-        table.pop_back(); 
+    void pop(TPrecisionQualifier *p)
+    {
+        table[currentLevel()]->getPreviousDefaultPrecisions(p);
+        delete table[currentLevel()];
+        table.pop_back();
     }
 
     bool insert(TSymbol& symbol)
@@ -284,8 +315,8 @@ public:
         symbol.setUniqueId(++uniqueId);
         return table[currentLevel()]->insert(symbol);
     }
-    
-    TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0) 
+
+    TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0)
     {
         int level = currentLevel();
         TSymbol* symbol;
@@ -307,7 +338,9 @@ public:
     void dump(TInfoSink &infoSink) const;
        void copyTable(const TSymbolTable& copyOf);
 
-protected:    
+    void setPreviousDefaultPrecisions(TPrecisionQualifier *p) { table[currentLevel()]->setPreviousDefaultPrecisions(p); }
+
+protected:
     int currentLevel() const { return static_cast<int>(table.size()) - 1; }
     bool atDynamicBuiltInLevel() { return table.size() == 2; }
 
index dd98d4e..4017075 100644 (file)
@@ -732,6 +732,24 @@ void SetVersion(int version)
 {\r
     TParseContext& parseContext = *((TParseContext *)cpp->pC);\r
     parseContext.version = version;\r
+\r
+       if (version == 100 || version == 300) {\r
+           for (int type = 0; type < EbtNumTypes; ++type)\r
+                   parseContext.defaultPrecision[type] = EpqNone;\r
+\r
+           if (parseContext.language == EShLangVertex) {\r
+                       parseContext.defaultPrecision[EbtInt] = EpqHigh;\r
+                       parseContext.defaultPrecision[EbtFloat] = EpqHigh;\r
+                       parseContext.defaultPrecision[EbtSampler2D] = EpqLow;\r
+                       parseContext.defaultPrecision[EbtSamplerCube] = EpqLow;\r
+        }\r
+\r
+        if (parseContext.language == EShLangFragment)  {\r
+                       parseContext.defaultPrecision[EbtInt] = EpqMedium;\r
+                       parseContext.defaultPrecision[EbtSampler2D] = EpqLow;\r
+                       parseContext.defaultPrecision[EbtSamplerCube] = EpqLow;\r
+        }\r
+       }\r
 }\r
 \r
 const int FirstProfileVersion = 150;\r
index 3281913..6263542 100644 (file)
@@ -96,7 +96,6 @@ Jutta Degener, 1995
         };\r
         union {\r
             TPublicType type;\r
-            TQualifier qualifier;\r
             TFunction* function;\r
             TParameter param;\r
             TTypeLine typeLine;\r
@@ -235,7 +234,7 @@ variable_identifier
         // don't delete $1.string, it's used by error recovery, and the pool\r
         // pop will reclaim the memory\r
 \r
-        if (variable->getType().getQualifier() == EvqConst ) {\r
+        if (variable->getType().getQualifier().storage == EvqConst ) {\r
             constUnion* constArray = variable->getConstPointer();\r
             TType t(variable->getType());\r
             $$ = parseContext.intermediate.addConstantUnion(constArray, t, $1.line);\r
@@ -293,7 +292,7 @@ postfix_expression
                 parseContext.error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression", "");\r
             parseContext.recover();\r
         }\r
-        if ($1->getType().getQualifier() == EvqConst && $3->getQualifier() == EvqConst) {\r
+        if ($1->getType().getQualifier().storage == EvqConst && $3->getQualifier().storage == EvqConst) {\r
             if ($1->isArray()) { // constant folding for arrays\r
                 $$ = parseContext.addConstArrayNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line);\r
             } else if ($1->isVector()) {  // constant folding for vectors\r
@@ -305,7 +304,7 @@ postfix_expression
                 $$ = parseContext.addConstMatrixNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line);\r
             }\r
         } else {\r
-            if ($3->getQualifier() == EvqConst) {\r
+            if ($3->getQualifier().storage == EvqConst) {\r
                 if (($1->isVector() || $1->isMatrix()) && $1->getType().getNominalSize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() && !$1->isArray() ) {\r
                     parseContext.error($2.line, "", "[", "field selection out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst());\r
                     parseContext.recover();\r
@@ -345,13 +344,13 @@ postfix_expression
             else\r
                 $$->setType(TType($1->getBasicType(), EvqTemporary, $1->getNominalSize(), $1->isMatrix()));\r
 \r
-            if ($1->getType().getQualifier() == EvqConst)\r
-                $$->getTypePointer()->changeQualifier(EvqConst);\r
-        } else if ($1->isMatrix() && $1->getType().getQualifier() == EvqConst)\r
+            if ($1->getType().getQualifier().storage == EvqConst)\r
+                $$->getTypePointer()->getQualifier().storage = EvqConst;\r
+        } else if ($1->isMatrix() && $1->getType().getQualifier().storage == EvqConst)\r
             $$->setType(TType($1->getBasicType(), EvqConst, $1->getNominalSize()));\r
         else if ($1->isMatrix())\r
             $$->setType(TType($1->getBasicType(), EvqTemporary, $1->getNominalSize()));\r
-        else if ($1->isVector() && $1->getType().getQualifier() == EvqConst)\r
+        else if ($1->isVector() && $1->getType().getQualifier().storage == EvqConst)\r
             $$->setType(TType($1->getBasicType(), EvqConst));\r
         else if ($1->isVector())\r
             $$->setType(TType($1->getBasicType(), EvqTemporary));\r
@@ -387,7 +386,7 @@ postfix_expression
                 parseContext.recover();\r
             }\r
 \r
-            if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields\r
+            if ($1->getType().getQualifier().storage == EvqConst) { // constant folding for vector fields\r
                 $$ = parseContext.addConstVectorNode(fields, $1, $3.line);\r
                 if ($$ == 0) {\r
                     parseContext.recover();\r
@@ -450,7 +449,7 @@ postfix_expression
                     }\r
                 }\r
                 if (fieldFound) {\r
-                    if ($1->getType().getQualifier() == EvqConst) {\r
+                    if ($1->getType().getQualifier().storage == EvqConst) {\r
                         $$ = parseContext.addConstStruct(*$3.string, $1, $2.line);\r
                         if ($$ == 0) {\r
                             parseContext.recover();\r
@@ -460,7 +459,7 @@ postfix_expression
                             $$->setType(*(*fields)[i].type);\r
                             // change the qualifier of the return type, not of the structure field\r
                             // as the structure definition is shared between various structures.\r
-                            $$->getTypePointer()->changeQualifier(EvqConst);\r
+                            $$->getTypePointer()->getQualifier().storage = EvqConst;\r
                         }\r
                     } else {\r
                         constUnion *unionArray = new constUnion[1];\r
@@ -593,10 +592,10 @@ function_call
                         $$->getAsAggregate()->setUserDefined();\r
                     $$->getAsAggregate()->setName(fnCandidate->getMangledName());\r
 \r
-                    TQualifier qual;\r
-                    TQualifierList& qualifierList = $$->getAsAggregate()->getQualifier();\r
+                    TStorageQualifier qual;\r
+                    TQualifierList& qualifierList = $$->getAsAggregate()->getQualifierList();\r
                     for (int i = 0; i < fnCandidate->getParamCount(); ++i) {\r
-                        qual = (*fnCandidate)[i].type->getQualifier();\r
+                        qual = (*fnCandidate)[i].type->getQualifier().storage;\r
                         if (qual == EvqOut || qual == EvqInOut) {\r
                             if (parseContext.lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) {\r
                                 parseContext.error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error", "");\r
@@ -682,6 +681,7 @@ function_identifier
             parseContext.profileRequires($1.line, ENoProfile, 120, "GL_3DL_array_objects", "array");\r
         }\r
 \r
+        $1.qualifier.precision = EpqNone;\r
         if ($1.userDef) {\r
             TString tempString = "";\r
             TType type($1);\r
@@ -1122,6 +1122,11 @@ declaration
     }\r
     | PRECISION precision_qualifier type_specifier SEMICOLON {\r
         parseContext.profileRequires($1.line, ENoProfile, 130, 0, "precision statement");\r
+        \r
+        // lazy setting of the previous scope's defaults, only takes on first one in a particular scope\r
+        parseContext.symbolTable.setPreviousDefaultPrecisions(&parseContext.defaultPrecision[0]);\r
+\r
+               parseContext.setDefaultPrecision($1.line, $3.type, $2.qualifier.precision);\r
         $$ = 0;\r
     }\r
     | type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE SEMICOLON {\r
@@ -1176,8 +1181,9 @@ function_prototype
                 parseContext.recover();\r
             }\r
             for (int i = 0; i < prevDec->getParamCount(); ++i) {\r
-                if ((*prevDec)[i].type->getQualifier() != (*$1)[i].type->getQualifier()) {\r
-                    parseContext.error($2.line, "overloaded functions must have the same parameter qualifiers", (*$1)[i].type->getQualifierString(), "");\r
+                if ((*prevDec)[i].type->getQualifier().storage != (*$1)[i].type->getQualifier().storage) {\r
+                    parseContext.error($2.line, "overloaded functions must have the same parameter qualifiers", \r
+                                       (*$1)[i].type->getStorageQualifierString(), "");\r
                     parseContext.recover();\r
                 }\r
             }\r
@@ -1236,8 +1242,9 @@ function_header_with_parameters
 \r
 function_header\r
     : fully_specified_type IDENTIFIER LEFT_PAREN {\r
-        if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) {\r
-            parseContext.error($2.line, "no qualifiers allowed for function return", getQualifierString($1.qualifier), "");\r
+        if ($1.qualifier.storage != EvqGlobal && $1.qualifier.storage != EvqTemporary) {\r
+            parseContext.error($2.line, "no qualifiers allowed for function return", \r
+                               getStorageQualifierString($1.qualifier.storage), "");\r
             parseContext.recover();\r
         }\r
         // make sure a sampler is not involved as well...\r
@@ -1261,6 +1268,7 @@ parameter_declarator
         }\r
         if (parseContext.reservedErrorCheck($2.line, *$2.string))\r
             parseContext.recover();\r
+        \r
         TParameter param = {$2.string, new TType($1)};\r
         $$.line = $2.line;\r
         $$.param = param;\r
@@ -1286,10 +1294,12 @@ parameter_declaration
     //\r
     : type_qualifier parameter_declarator {\r
         $$ = $2;\r
+        if ($1.qualifier.precision != EpqNone)\r
+            $$.param.type->getQualifier().precision = $1.qualifier.precision;\r
 \r
-        if (parseContext.parameterSamplerErrorCheck($2.line, $1.qualifier, *$2.param.type))\r
+        if (parseContext.parameterSamplerErrorCheck($2.line, $1.qualifier.storage, *$$.param.type))\r
             parseContext.recover();\r
-        if (parseContext.paramErrorCheck($1.line, $1.qualifier, $$.param.type))\r
+        if (parseContext.paramErrorCheck($1.line, $1.qualifier.storage, $$.param.type))\r
             parseContext.recover();\r
     }\r
     | parameter_declarator {\r
@@ -1305,16 +1315,18 @@ parameter_declaration
     //\r
     | type_qualifier parameter_type_specifier {\r
         $$ = $2;\r
+        if ($1.qualifier.precision != EpqNone)\r
+            $$.param.type->getQualifier().precision = $1.qualifier.precision;\r
         \r
-        if (parseContext.parameterSamplerErrorCheck($2.line, $1.qualifier, *$2.param.type))\r
+        if (parseContext.parameterSamplerErrorCheck($2.line, $1.qualifier.storage, *$$.param.type))\r
             parseContext.recover();\r
-        if (parseContext.paramErrorCheck($1.line, $1.qualifier, $$.param.type))\r
+        if (parseContext.paramErrorCheck($1.line, $1.qualifier.storage, $$.param.type))\r
             parseContext.recover();\r
     }\r
     | parameter_type_specifier {\r
         $$ = $1;\r
 \r
-        if (parseContext.parameterSamplerErrorCheck($1.line, $1.qualifier, *$1.param.type))\r
+        if (parseContext.parameterSamplerErrorCheck($1.line, EvqIn, *$1.param.type))\r
             parseContext.recover();\r
         if (parseContext.paramErrorCheck($1.line, EvqTemporary, $$.param.type))\r
             parseContext.recover();\r
@@ -1535,18 +1547,20 @@ fully_specified_type
             $2.setArray(false);\r
         }\r
 \r
-        if ($1.qualifier == EvqAttribute &&\r
+        if ($1.qualifier.storage == EvqAttribute &&\r
             ($2.type == EbtBool || $2.type == EbtInt)) {\r
-            parseContext.error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), "");\r
+            parseContext.error($2.line, "cannot be bool or int", getStorageQualifierString($1.qualifier.storage), "");\r
             parseContext.recover();\r
         }\r
-        if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) &&\r
+        if (($1.qualifier.storage == EvqVaryingIn || $1.qualifier.storage == EvqVaryingOut) &&\r
             ($2.type == EbtBool || $2.type == EbtInt)) {\r
-            parseContext.error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), "");\r
+            parseContext.error($2.line, "cannot be bool or int", getStorageQualifierString($1.qualifier.storage), "");\r
             parseContext.recover();\r
         }\r
         $$ = $2;\r
         $$.qualifier = $1.qualifier;\r
+        if ($$.qualifier.precision == EpqNone)\r
+            $$.qualifier.precision = $2.qualifier.precision;\r
     }\r
     ;\r
 \r
@@ -1601,15 +1615,18 @@ type_qualifier
             $$.type = $2.type;\r
         }\r
 \r
-        if ($$.qualifier == EvqTemporary) {\r
-            $$.qualifier = $2.qualifier;\r
-        } else if ($$.qualifier == EvqIn  && $2.qualifier == EvqOut ||\r
-                   $$.qualifier == EvqOut && $2.qualifier == EvqIn) {\r
-            $$.qualifier = EvqInOut;\r
-        } else if ($$.qualifier == EvqIn    && $2.qualifier == EvqConst ||\r
-                   $$.qualifier == EvqConst && $2.qualifier == EvqIn) {\r
-            $$.qualifier = EvqConstReadOnly;\r
+        if ($$.qualifier.storage == EvqTemporary) {\r
+            $$.qualifier.storage = $2.qualifier.storage;\r
+        } else if ($$.qualifier.storage == EvqIn  && $2.qualifier.storage == EvqOut ||\r
+                   $$.qualifier.storage == EvqOut && $2.qualifier.storage == EvqIn) {\r
+            $$.qualifier.storage = EvqInOut;\r
+        } else if ($$.qualifier.storage == EvqIn    && $2.qualifier.storage == EvqConst ||\r
+                   $$.qualifier.storage == EvqConst && $2.qualifier.storage == EvqIn) {\r
+            $$.qualifier.storage = EvqConstReadOnly;\r
         }\r
+\r
+        if ($$.qualifier.precision == EpqNone)\r
+            $$.qualifier.precision = $2.qualifier.precision;\r
     }\r
     ;\r
 \r
@@ -1639,7 +1656,8 @@ single_type_qualifier
 \r
 storage_qualifier\r
     : CONST {\r
-        $$.setBasic(EbtVoid, EvqConst, $1.line);\r
+        $$.init($1.line);\r
+        $$.qualifier.storage = EvqConst;\r
     }\r
     | ATTRIBUTE {\r
         parseContext.requireStage($1.line, EShLangVertexMask, "attribute");\r
@@ -1649,7 +1667,9 @@ storage_qualifier
 \r
         if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "attribute"))\r
             parseContext.recover();\r
-        $$.setBasic(EbtVoid, EvqAttribute, $1.line);\r
+\r
+        $$.init($1.line);\r
+        $$.qualifier.storage = EvqAttribute;\r
     }\r
     | VARYING {\r
         parseContext.checkDeprecated($1.line, ENoProfile, 140, "varying");\r
@@ -1657,97 +1677,115 @@ storage_qualifier
         \r
         if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "varying"))\r
             parseContext.recover();\r
-        if (parseContext.language == EShLangVertex)\r
-            $$.setBasic(EbtVoid, EvqVaryingOut, $1.line);\r
+\r
+        $$.init($1.line);\r
+        if (parseContext.language == EShLangVertex)            \r
+            $$.qualifier.storage = EvqVaryingOut;\r
         else\r
-            $$.setBasic(EbtVoid, EvqVaryingIn, $1.line);\r
+            $$.qualifier.storage = EvqVaryingIn;\r
     }\r
     | INOUT {\r
         if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "out"))\r
             parseContext.recover();\r
-        $$.setBasic(EbtVoid, EvqInOut, $1.line);\r
+        $$.init($1.line);\r
+        $$.qualifier.storage = EvqInOut;\r
     }\r
     | IN {\r
         if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "in"))\r
             parseContext.recover();\r
-        $$.setBasic(EbtVoid, EvqIn, $1.line);\r
+        $$.init($1.line);\r
+        $$.qualifier.storage = EvqIn;\r
     }\r
     | OUT {\r
         if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "out"))\r
             parseContext.recover();\r
-        $$.setBasic(EbtVoid, EvqOut, $1.line);\r
+        $$.init($1.line);\r
+        $$.qualifier.storage = EvqOut;\r
     }\r
     | CENTROID {\r
         if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "centroid"))\r
             parseContext.recover();\r
-        $$.setBasic(EbtVoid, EvqVaryingIn, $1.line);\r
+        $$.init($1.line);\r
+        $$.qualifier.storage = EvqVaryingIn;\r
     }\r
     | PATCH {\r
         // TODO: implement this qualifier\r
         if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "patch"))\r
             parseContext.recover();\r
-        $$.setBasic(EbtVoid, EvqUniform, $1.line);\r
+        $$.init($1.line);\r
+        $$.qualifier.storage = EvqUniform;\r
     }\r
     | SAMPLE {\r
         // TODO: implement this qualifier\r
         if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "sample"))\r
             parseContext.recover();\r
-        $$.setBasic(EbtVoid, EvqUniform, $1.line);\r
+        $$.init($1.line);\r
+        $$.qualifier.storage = EvqUniform;\r
     }\r
     | UNIFORM {\r
         if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "uniform"))\r
             parseContext.recover();\r
-        $$.setBasic(EbtVoid, EvqUniform, $1.line);\r
+        $$.init($1.line);\r
+        $$.qualifier.storage = EvqUniform;\r
     }\r
     | BUFFER {\r
         if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "buffer"))\r
             parseContext.recover();\r
-        $$.setBasic(EbtVoid, EvqUniform, $1.line);\r
+        $$.init($1.line);\r
+        $$.qualifier.storage = EvqUniform;\r
     }\r
     | SHARED {\r
         if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "shared"))\r
             parseContext.recover();\r
-        $$.setBasic(EbtVoid, EvqUniform, $1.line);\r
+        $$.init($1.line);\r
+        $$.qualifier.storage = EvqUniform;\r
     }\r
     | COHERENT {\r
         // TODO: implement this qualifier\r
         if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "coherent"))\r
             parseContext.recover();\r
-        $$.setBasic(EbtVoid, EvqUniform, $1.line);\r
+        $$.init($1.line);\r
+        $$.qualifier.storage = EvqUniform;\r
     }\r
     | VOLATILE {\r
         // TODO: implement this qualifier\r
         if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "volatile"))\r
             parseContext.recover();\r
-        $$.setBasic(EbtVoid, EvqUniform, $1.line);\r
+        $$.init($1.line);\r
+        $$.qualifier.storage = EvqUniform;\r
     }\r
     | RESTRICT {\r
         // TODO: implement this qualifier\r
         if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "restrict"))\r
             parseContext.recover();\r
-        $$.setBasic(EbtVoid, EvqUniform, $1.line);\r
+        $$.init($1.line);\r
+        $$.qualifier.storage = EvqUniform;\r
     }\r
     | READONLY {\r
         // TODO: implement this qualifier\r
         if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "readonly"))\r
             parseContext.recover();\r
-        $$.setBasic(EbtVoid, EvqUniform, $1.line);\r
+        $$.init($1.line);\r
+        $$.qualifier.storage = EvqUniform;\r
     }\r
     | WRITEONLY {\r
         // TODO: implement this qualifier\r
         if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "writeonly"))\r
             parseContext.recover();\r
-        $$.setBasic(EbtVoid, EvqUniform, $1.line);\r
+        $$.init($1.line);\r
+        $$.qualifier.storage = EvqUniform;\r
     }\r
     | SUBROUTINE {\r
         if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "subroutine"))\r
             parseContext.recover();\r
-        $$.setBasic(EbtVoid, EvqUniform, $1.line);\r
+        $$.init($1.line);\r
+        $$.qualifier.storage = EvqUniform;\r
     }\r
     | SUBROUTINE LEFT_PAREN type_name_list RIGHT_PAREN {\r
         if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "subroutine"))\r
             parseContext.recover();\r
-        $$.setBasic(EbtVoid, EvqUniform, $1.line);\r
+        $$.init($1.line);\r
+        $$.qualifier.storage = EvqUniform;\r
         // TODO: subroutine semantics\r
         // 1) make sure each identifier is a type declared earlier with SUBROUTINE\r
         // 2) save all of the identifiers for future comparison with the declared function\r
@@ -1766,9 +1804,11 @@ type_name_list
 type_specifier\r
     : type_specifier_nonarray {\r
         $$ = $1;\r
+        $$.qualifier.precision = parseContext.defaultPrecision[$$.type];\r
     }\r
     | type_specifier_nonarray array_specifier {\r
         $$ = $1;\r
+        $$.qualifier.precision = parseContext.defaultPrecision[$$.type];\r
         $$.setArray(true, $2.intVector->front());\r
     }\r
     ;\r
@@ -1804,588 +1844,587 @@ array_specifier
 \r
 type_specifier_nonarray\r
     : VOID {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtVoid, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtVoid;\r
     }\r
     | FLOAT {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtFloat;\r
     }\r
     | DOUBLE {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        // TODO: implement EbtDouble, check all float types\r
-        $$.setBasic(EbtDouble, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtDouble;\r
     }\r
     | INT {\r
-        // TODO: implement EbtUint, check all int types\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtInt, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtInt;\r
     }\r
     | UINT {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtInt, qual, $1.line);\r
+        // TODO: implement EbtUint, check all int types\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtInt;\r
     }\r
     | BOOL {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtBool, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtBool;\r
     }\r
     | VEC2 {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtFloat;\r
         $$.setAggregate(2);\r
     }\r
     | VEC3 {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtFloat;\r
         $$.setAggregate(3);\r
     }\r
     | VEC4 {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtFloat;\r
         $$.setAggregate(4);\r
     }\r
     | DVEC2 {\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtDouble;\r
+        $$.setAggregate(2);\r
     }\r
     | DVEC3 {\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtDouble;\r
+        $$.setAggregate(3);\r
     }\r
     | DVEC4 {\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtDouble;\r
+        $$.setAggregate(4);\r
     }\r
     | BVEC2 {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtBool, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtBool;\r
         $$.setAggregate(2);\r
     }\r
     | BVEC3 {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtBool, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtBool;\r
         $$.setAggregate(3);\r
     }\r
     | BVEC4 {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtBool, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtBool;\r
         $$.setAggregate(4);\r
     }\r
     | IVEC2 {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtInt, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtInt;\r
         $$.setAggregate(2);\r
     }\r
     | IVEC3 {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtInt, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtInt;\r
         $$.setAggregate(3);\r
     }\r
     | IVEC4 {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtInt, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtInt;\r
         $$.setAggregate(4);\r
     }\r
     | UVEC2 {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtInt, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtInt;\r
         $$.setAggregate(2);\r
     }\r
     | UVEC3 {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtInt, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtInt;\r
         $$.setAggregate(3);\r
     }\r
     | UVEC4 {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtInt, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtInt;\r
         $$.setAggregate(4);\r
     }\r
     | MAT2 {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtFloat;\r
         $$.setAggregate(2, true);\r
     }\r
     | MAT3 {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtFloat;\r
         $$.setAggregate(3, true);\r
     }\r
     | MAT4 {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtFloat;\r
         $$.setAggregate(4, true);\r
     }\r
     | MAT2X2 {\r
-        // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
-        $$.setAggregate(4, true);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtFloat;\r
+        $$.setAggregate(2, true);\r
     }\r
     | MAT2X3 {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
-        $$.setAggregate(4, true);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtFloat;\r
+        $$.setAggregate(3, true);\r
     }\r
     | MAT2X4 {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtFloat;\r
         $$.setAggregate(4, true);\r
     }\r
     | MAT3X2 {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
-        $$.setAggregate(4, true);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtFloat;\r
+        $$.setAggregate(3, true);\r
     }\r
     | MAT3X3 {\r
-        // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
-        $$.setAggregate(4, true);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtFloat;\r
+        $$.setAggregate(3, true);\r
     }\r
     | MAT3X4 {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtFloat;\r
         $$.setAggregate(4, true);\r
     }\r
     | MAT4X2 {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtFloat;\r
         $$.setAggregate(4, true);\r
     }\r
     | MAT4X3 {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtFloat;\r
         $$.setAggregate(4, true);\r
     }\r
     | MAT4X4 {\r
-        // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtFloat;\r
         $$.setAggregate(4, true);\r
     }\r
     | DMAT2 {\r
-        // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
-        $$.setAggregate(4, true);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtDouble;\r
+        $$.setAggregate(2, true);\r
     }\r
     | DMAT3 {\r
-        // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
-        $$.setAggregate(4, true);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtDouble;\r
+        $$.setAggregate(3, true);\r
     }\r
     | DMAT4 {\r
-        // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtDouble;\r
         $$.setAggregate(4, true);\r
     }\r
     | DMAT2X2 {\r
-        // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
-        $$.setAggregate(4, true);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtDouble;\r
+        $$.setAggregate(2, true);\r
     }\r
     | DMAT2X3 {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
-        $$.setAggregate(4, true);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtDouble;\r
+        $$.setAggregate(3, true);\r
     }\r
     | DMAT2X4 {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtDouble;\r
         $$.setAggregate(4, true);\r
     }\r
     | DMAT3X2 {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
-        $$.setAggregate(4, true);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtDouble;\r
+        $$.setAggregate(3, true);\r
     }\r
     | DMAT3X3 {\r
-        // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
-        $$.setAggregate(4, true);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtDouble;\r
+        $$.setAggregate(3, true);\r
     }\r
     | DMAT3X4 {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtDouble;\r
         $$.setAggregate(4, true);\r
     }\r
     | DMAT4X2 {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtDouble;\r
         $$.setAggregate(4, true);\r
     }\r
     | DMAT4X3 {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtDouble;\r
         $$.setAggregate(4, true);\r
     }\r
     | DMAT4X4 {\r
-        // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtFloat, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtDouble;\r
         $$.setAggregate(4, true);\r
     }\r
     | ATOMIC_UINT {\r
         // TODO: add type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtInt, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtInt;\r
     }\r
     | SAMPLER1D {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler1D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler1D;\r
     }\r
     | SAMPLER2D {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | SAMPLER3D {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler3D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler3D;\r
     }\r
     | SAMPLERCUBE {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSamplerCube, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSamplerCube;\r
     }\r
     | SAMPLER1DSHADOW {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler1DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler1DShadow;\r
     }\r
     | SAMPLER2DSHADOW {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | SAMPLERCUBESHADOW {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | SAMPLER1DARRAY {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | SAMPLER2DARRAY {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | SAMPLER1DARRAYSHADOW {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | SAMPLER2DARRAYSHADOW {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | SAMPLERCUBEARRAY {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | SAMPLERCUBEARRAYSHADOW {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | ISAMPLER1D {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | ISAMPLER2D {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | ISAMPLER3D {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | ISAMPLERCUBE {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | ISAMPLER1DARRAY {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | ISAMPLER2DARRAY {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | ISAMPLERCUBEARRAY {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | USAMPLER1D {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | USAMPLER2D {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | USAMPLER3D {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | USAMPLERCUBE {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | USAMPLER1DARRAY {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | USAMPLER2DARRAY {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | USAMPLERCUBEARRAY {\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2DShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2DShadow;\r
     }\r
     | SAMPLER2DRECT {\r
         parseContext.profileRequires($1.line, ENoProfile, 140, "GL_ARB_texture_rectangle", "rectangle texture");\r
 \r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSamplerRect, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSamplerRect;\r
     }\r
     | SAMPLER2DRECTSHADOW {\r
         parseContext.profileRequires($1.line, ECoreProfile, 140, "GL_ARB_texture_rectangle", "rectangle texture");\r
 \r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSamplerRectShadow, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSamplerRectShadow;\r
     }\r
     | ISAMPLER2DRECT {\r
         parseContext.profileRequires($1.line, ECoreProfile, 140, "GL_ARB_texture_rectangle", "rectangle texture");\r
 \r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSamplerRect, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSamplerRect;\r
     }\r
     | USAMPLER2DRECT {\r
         parseContext.profileRequires($1.line, ECoreProfile, 140, "GL_ARB_texture_rectangle", "rectangle texture");\r
 \r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSamplerRect, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSamplerRect;\r
     }\r
     | SAMPLERBUFFER {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | ISAMPLERBUFFER {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | USAMPLERBUFFER {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | SAMPLER2DMS {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | ISAMPLER2DMS {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | USAMPLER2DMS {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | SAMPLER2DMSARRAY {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | ISAMPLER2DMSARRAY {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | USAMPLER2DMSARRAY {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IMAGE1D {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IIMAGE1D {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | UIMAGE1D {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IMAGE2D {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IIMAGE2D {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | UIMAGE2D {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IMAGE3D {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IIMAGE3D {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | UIMAGE3D {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IMAGE2DRECT {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IIMAGE2DRECT {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | UIMAGE2DRECT {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IMAGECUBE {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IIMAGECUBE {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | UIMAGECUBE {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IMAGEBUFFER {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IIMAGEBUFFER {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | UIMAGEBUFFER {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IMAGE1DARRAY {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IIMAGE1DARRAY {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | UIMAGE1DARRAY {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IMAGE2DARRAY {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IIMAGE2DARRAY {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | UIMAGE2DARRAY {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IMAGECUBEARRAY {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IIMAGECUBEARRAY {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | UIMAGECUBEARRAY {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IMAGE2DMS {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IIMAGE2DMS {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | UIMAGE2DMS {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IMAGE2DMSARRAY {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | IIMAGE2DMSARRAY {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | UIMAGE2DMSARRAY {\r
         // TODO: implement this type\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtSampler2D, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtSampler2D;\r
     }\r
     | struct_specifier {\r
         $$ = $1;\r
-        $$.qualifier = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
+        $$.qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
     }\r
     | TYPE_NAME {\r
         //\r
@@ -2393,8 +2432,8 @@ type_specifier_nonarray
         // type.\r
         //\r
         TType& structure = static_cast<TVariable*>($1.symbol)->getType();\r
-        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;\r
-        $$.setBasic(EbtStruct, qual, $1.line);\r
+        $$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
+        $$.type = EbtStruct;\r
         $$.userDef = &structure;\r
     }\r
     ;\r
@@ -2402,12 +2441,18 @@ type_specifier_nonarray
 precision_qualifier\r
     : HIGH_PRECISION {\r
         parseContext.profileRequires($1.line, ENoProfile, 130, 0, "highp precision qualifier");\r
+        $$.init($1.line);\r
+               $$.qualifier.precision = EpqHigh;\r
     }\r
     | MEDIUM_PRECISION {\r
         parseContext.profileRequires($1.line, ENoProfile, 130, 0, "mediump precision qualifier");\r
+        $$.init($1.line);\r
+               $$.qualifier.precision = EpqMedium;\r
     }\r
     | LOW_PRECISION {\r
         parseContext.profileRequires($1.line, ENoProfile, 130, 0, "lowp precision qualifier");\r
+        $$.init($1.line);\r
+               $$.qualifier.precision = EpqLow;\r
     }\r
     ;\r
 \r
@@ -2419,12 +2464,14 @@ struct_specifier
             parseContext.error($2.line, "redefinition", $2.string->c_str(), "struct");\r
             parseContext.recover();\r
         }\r
-        $$.setBasic(EbtStruct, EvqTemporary, $1.line);\r
+        $$.init($1.line);\r
+        $$.type = EbtStruct;\r
         $$.userDef = structure;\r
     }\r
     | STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE {\r
         TType* structure = new TType($3, TString(""));\r
-        $$.setBasic(EbtStruct, EvqTemporary, $1.line);\r
+        $$.init($1.line);\r
+        $$.type = EbtStruct;\r
         $$.userDef = structure;\r
     }\r
     ;\r
@@ -2555,7 +2602,9 @@ simple_statement
 \r
 compound_statement\r
     : LEFT_BRACE RIGHT_BRACE { $$ = 0; }\r
-    | LEFT_BRACE { parseContext.symbolTable.push(); } statement_list { parseContext.symbolTable.pop(); } RIGHT_BRACE {\r
+    | LEFT_BRACE { parseContext.symbolTable.push(); } \r
+      statement_list { parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); } \r
+      RIGHT_BRACE {\r
         if ($3 != 0)\r
             $3->setOperator(EOpSequence);\r
         $$ = $3;\r
@@ -2660,8 +2709,12 @@ case_label
     ;\r
 \r
 iteration_statement\r
-    : WHILE LEFT_PAREN { parseContext.symbolTable.push(); ++parseContext.loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope {\r
-        parseContext.symbolTable.pop();\r
+    : WHILE LEFT_PAREN { \r
+        parseContext.symbolTable.push(); \r
+        ++parseContext.loopNestingLevel; \r
+    }\r
+      condition RIGHT_PAREN statement_no_new_scope {\r
+        parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);\r
         $$ = parseContext.intermediate.addLoop($6, $4, 0, true, $1.line);\r
         --parseContext.loopNestingLevel;\r
     }\r
@@ -2672,8 +2725,12 @@ iteration_statement
         $$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.line);\r
         --parseContext.loopNestingLevel;\r
     }\r
-    | FOR LEFT_PAREN { parseContext.symbolTable.push(); ++parseContext.loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {\r
-        parseContext.symbolTable.pop();\r
+    | FOR LEFT_PAREN { \r
+        parseContext.symbolTable.push();\r
+        ++parseContext.loopNestingLevel; \r
+    } \r
+      for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {\r
+        parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);\r
         $$ = parseContext.intermediate.makeAggregate($4, $2.line);\r
         $$ = parseContext.intermediate.growAggregate(\r
                 $$,\r
@@ -2867,7 +2924,7 @@ function_definition
             parseContext.error($1.line, "function does not return a value:", "", $1.function->getName().c_str());\r
             parseContext.recover();\r
         }\r
-        parseContext.symbolTable.pop();\r
+        parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);\r
         $$ = parseContext.intermediate.growAggregate($1.intermAggregate, $3, 0);\r
         parseContext.intermediate.setAggregateOperator($$, EOpFunction, $1.line);\r
         $$->getAsAggregate()->setName($1.function->getMangledName().c_str());\r
index b5df824..42252f8 100644 (file)
@@ -60,10 +60,12 @@ TString TType::getCompleteString() const
     char *p = &buf[0];
        char *end = &buf[maxSize];
 
-    if (qualifier != EvqTemporary && qualifier != EvqGlobal)
-        p += sprintf_s(p, end - p, "%s ", getQualifierString());
+    if (qualifier.storage != EvqTemporary && qualifier.storage != EvqGlobal)
+        p += sprintf_s(p, end - p, "%s ", getStorageQualifierString());
     if (array)
         p += sprintf_s(p, end - p, "array of ");
+    if (qualifier.precision != EpqNone)
+        p += sprintf_s(p, end - p, "%s ", getPrecisionQualifierString());
     if (matrix)
         p += sprintf_s(p, end - p, "%dX%d matrix of ", size, size);
     else if (size > 1)
index 3497d8c..25e721f 100644 (file)
@@ -69,15 +69,15 @@ void ParseSymbol(TIntermSymbol* node, TIntermTraverser* it)
 {
     TConstTraverser* oit = static_cast<TConstTraverser*>(it);
     oit->infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
-    return;
 
+    return;
 }
 
 bool ParseBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
 {
     TConstTraverser* oit = static_cast<TConstTraverser*>(it);
     
-    TQualifier qualifier = node->getType().getQualifier();
+    TStorageQualifier qualifier = node->getType().getQualifier().storage;
     
     if (qualifier != EvqConst) {
                const int maxSize = 200;
@@ -85,6 +85,7 @@ bool ParseBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
         sprintf_s(buf, maxSize, "'constructor' : assigning non-constant to %s", oit->type.getCompleteString().c_str());
         oit->infoSink.info.message(EPrefixError, buf, node->getLine());
         oit->error = true;
+
         return false;  
     }
 
@@ -102,6 +103,7 @@ bool ParseUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it)
     sprintf_s(buf, maxSize, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
     oit->infoSink.info.message(EPrefixError, buf, node->getLine());
     oit->error = true;
+
     return false;  
 }
 
@@ -115,11 +117,13 @@ bool ParseAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverse
         sprintf_s(buf, maxSize, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
         oit->infoSink.info.message(EPrefixError, buf, node->getLine());
         oit->error = true;
+
         return false;  
     }
 
     if (node->getSequence().size() == 0) {
         oit->error = true;
+
         return false;
     }
 
@@ -152,6 +156,7 @@ bool ParseAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverse
         oit->isMatrix = false;
         oit->matrixSize = 0;
     }
+
     return false;
 }
 
@@ -229,6 +234,7 @@ bool ParseLoop(bool /* preVisit */, TIntermLoop* node, TIntermTraverser* it)
     TConstTraverser* oit = static_cast<TConstTraverser*>(it);
     oit->infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
     oit->error = true;
+    
     return false;
 }
 
@@ -237,6 +243,7 @@ bool ParseBranch(bool /* previsit*/, TIntermBranch* node, TIntermTraverser* it)
     TConstTraverser* oit = static_cast<TConstTraverser*>(it);
     oit->infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
     oit->error = true;
+    
     return false;
 }