HLSL non-functional: Generalize namespace nesting.
authorJohn Kessenich <cepheus@frii.com>
Sun, 19 Mar 2017 18:24:29 +0000 (12:24 -0600)
committerJohn Kessenich <cepheus@frii.com>
Sun, 19 Mar 2017 19:01:58 +0000 (13:01 -0600)
Also use this to move deferred member-function-body parsing to a better
place.

This should also be well poised for implementing the 'namespace' keyword.

glslang/Include/revision.h
glslang/MachineIndependent/ParseHelper.h
hlsl/hlslAttributes.h
hlsl/hlslGrammar.cpp
hlsl/hlslGrammar.h
hlsl/hlslParseHelper.cpp
hlsl/hlslParseHelper.h

index e4ff5c621c98dbb29b4242c5f83c690545bc1c99..eaae2ce6b0854f821983c595b794d08c5b4cb45a 100644 (file)
@@ -2,5 +2,5 @@
 // For the version, it uses the latest git tag followed by the number of commits.
 // For the date, it uses the current date (when then script is run).
 
-#define GLSLANG_REVISION "Overload400-PrecQual.1920"
-#define GLSLANG_DATE "16-Mar-2017"
+#define GLSLANG_REVISION "Overload400-PrecQual.1921"
+#define GLSLANG_DATE "19-Mar-2017"
index ff4a3945bba91f928e5489a69a0032e3a8d84029..035b0fd0aef580b1a6325c983046d7c6e0745856 100644 (file)
@@ -145,6 +145,8 @@ public:
     virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
     virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
 
+    const char* const scopeMangler = "::";
+
 protected:
     TParseContextBase(TParseContextBase&);
     TParseContextBase& operator=(TParseContextBase&);
index e093760cb229bf0d588f574d4e3ee20342f23079..ad44d2ab199ead042ef5b2085425161e87e2cb74 100644 (file)
@@ -95,9 +95,11 @@ namespace glslang {
 
     class TFunctionDeclarator {
     public:
+        TFunctionDeclarator() : function(nullptr), body(nullptr) { }
         TSourceLoc loc;
         TFunction* function;
         TAttributeMap attributes;
+        TVector<HlslToken>* body;
     };
 
 } // end namespace glslang
index 1dc500bb70fa9489d493802230e332a178c337cd..be58dbc07797528c8808dab293dacd41bf8d9185 100755 (executable)
@@ -1788,7 +1788,7 @@ bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList)
     postDeclQualifier.clear();
     bool postDeclsFound = acceptPostDecls(postDeclQualifier);
 
-    // LEFT_BRACE
+    // LEFT_BRACE, or
     // struct_type IDENTIFIER
     if (! acceptTokenClass(EHTokLeftBrace)) {
         if (structName.size() > 0 && !postDeclsFound && parseContext.lookupUserType(structName, type) != nullptr) {
@@ -1800,9 +1800,17 @@ bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList)
         }
     }
 
+
     // struct_declaration_list
     TTypeList* typeList;
-    if (! acceptStructDeclarationList(typeList, nodeList, structName)) {
+    // Save each member function so they can be processed after we have a fully formed 'this'.
+    TVector<TFunctionDeclarator> functionDeclarators;
+
+    parseContext.pushNamespace(structName);
+    bool acceptedList = acceptStructDeclarationList(typeList, nodeList, structName, functionDeclarators);
+    parseContext.popNamespace();
+
+    if (! acceptedList) {
         expected("struct member declarations");
         return false;
     }
@@ -1823,7 +1831,20 @@ bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList)
 
     parseContext.declareStruct(token.loc, structName, type);
 
-    return true;
+    // All member functions get parsed inside the class/struct namespace and with the
+    // class/struct members in a symbol-table level.
+    parseContext.pushNamespace(structName);
+    bool deferredSuccess = true;
+    for (int b = 0; b < (int)functionDeclarators.size() && deferredSuccess; ++b) {
+        // parse body
+        pushTokenStream(functionDeclarators[b].body);
+        if (! acceptFunctionBody(functionDeclarators[b], nodeList))
+            deferredSuccess = false;
+        popTokenStream();
+    }
+    parseContext.popNamespace();
+
+    return deferredSuccess;
 }
 
 // struct_buffer
@@ -1934,16 +1955,12 @@ bool HlslGrammar::acceptStructBufferType(TType& type)
 //      | IDENTIFIER array_specifier post_decls
 //      | IDENTIFIER function_parameters post_decls                                         // member-function prototype
 //
-bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*& nodeList, const TString& typeName)
+bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*& nodeList, const TString& typeName,
+                                              TVector<TFunctionDeclarator>& declarators)
 {
     typeList = new TTypeList();
     HlslToken idToken;
 
-    // Save these away for each member function so they can be processed after
-    // all member variables/types have been declared.
-    TVector<TVector<HlslToken>*> memberBodies;
-    TVector<TFunctionDeclarator> declarators;
-
     do {
         // success on seeing the RIGHT_BRACE coming up
         if (peekTokenClass(EHTokRightBrace))
@@ -1973,11 +1990,8 @@ bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*
                 if (!declarator_list) {
                     declarators.resize(declarators.size() + 1);
                     // request a token stream for deferred processing
-                    TVector<HlslToken>* deferredTokens = new TVector<HlslToken>;
-                    functionDefinitionAccepted = acceptMemberFunctionDefinition(nodeList, typeName, memberType,
-                                                                                *idToken.string, declarators.back(),
-                                                                                deferredTokens);
-                    memberBodies.push_back(deferredTokens);
+                    functionDefinitionAccepted = acceptMemberFunctionDefinition(nodeList, memberType, *idToken.string,
+                                                                                declarators.back());
                     if (functionDefinitionAccepted)
                         break;
                 }
@@ -2030,14 +2044,6 @@ bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*
 
     } while (true);
 
-    // parse member-function bodies now
-    for (int b = 0; b < (int)memberBodies.size(); ++b) {
-        pushTokenStream(memberBodies[b]);
-        if (! acceptFunctionBody(declarators[b], nodeList))
-            return false;
-        popTokenStream();
-    }
-
     return true;
 }
 
@@ -2046,15 +2052,12 @@ bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*
 //
 // Expects type to have EvqGlobal for a static member and
 // EvqTemporary for non-static member.
-bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TString& typeName,
-                                                 const TType& type, const TString& memberName,
-                                                 TFunctionDeclarator& declarator, TVector<HlslToken>* deferredTokens)
+bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TType& type, const TString& memberName,
+                                                 TFunctionDeclarator& declarator)
 {
-    // watch early returns...
-    parseContext.pushThis(typeName);
     bool accepted = false;
 
-    TString* functionName = parseContext.getFullMemberFunctionName(memberName, type.getQualifier().storage == EvqGlobal);
+    TString* functionName = parseContext.getFullNamespaceName(memberName);
     declarator.function = new TFunction(functionName, type);
 
     // function_parameters
@@ -2070,12 +2073,12 @@ bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const T
             }
 
             declarator.loc = token.loc;
-            accepted = acceptFunctionDefinition(declarator, nodeList, deferredTokens);
+            declarator.body = new TVector<HlslToken>;
+            accepted = acceptFunctionDefinition(declarator, nodeList, declarator.body);
         }
     } else
         expected("function parameter list");
 
-    parseContext.popThis();
     return accepted;
 }
 
@@ -2781,13 +2784,8 @@ bool HlslGrammar::acceptFunctionCall(HlslToken callToken, TIntermTyped*& node, T
         functionName = callToken.string;
     else {
         functionName = NewPoolTString("");
-        if (baseObject != nullptr) {
-            functionName->append(baseObject->getType().getTypeName().c_str());
-            functionName->append(".");
-        } else if (baseType != nullptr) {
-            functionName->append(baseType->getType().getTypeName());
-            functionName->append("::");
-        }
+        functionName->append(baseType->getType().getTypeName());
+        parseContext.addScopeMangler(*functionName);
         functionName->append(*callToken.string);
     }
 
@@ -2795,7 +2793,6 @@ bool HlslGrammar::acceptFunctionCall(HlslToken callToken, TIntermTyped*& node, T
     TFunction* function = new TFunction(functionName, TType(EbtVoid));
 
     // arguments
-    // Non-static member functions have an implicit first argument of the base object.
     TIntermTyped* arguments = nullptr;
     if (baseObject != nullptr)
         parseContext.handleFunctionArgument(function, arguments, baseObject);
index e95fab0de9fe695544d70fdc472a2f6315327203..968364fa9caa8c32e001c765ff640d3c345a483c 100755 (executable)
@@ -87,10 +87,10 @@ namespace glslang {
         bool acceptTextureType(TType&);
         bool acceptStructBufferType(TType&);
         bool acceptStruct(TType&, TIntermNode*& nodeList);
-        bool acceptStructDeclarationList(TTypeList*&, TIntermNode*& nodeList, const TString& typeName);
-        bool acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TString& typeName,
-                                            const TType&, const TString& memberName, TFunctionDeclarator&,
-                                            TVector<HlslToken>* deferredTokens);
+        bool acceptStructDeclarationList(TTypeList*&, TIntermNode*& nodeList, const TString& typeName,
+                                         TVector<TFunctionDeclarator>&);
+        bool acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TType&, const TString& memberName,
+                                            TFunctionDeclarator&);
         bool acceptFunctionParameters(TFunction&);
         bool acceptParameterDeclaration(TFunction&);
         bool acceptFunctionDefinition(TFunctionDeclarator&, TIntermNode*& nodeList, TVector<HlslToken>* deferredTokens);
index 34cf5d37d5b9a3684725e7228967de9f214ce5ca..f30acbed321e908202e821d51828aa27beaadf0d 100755 (executable)
@@ -7085,7 +7085,7 @@ TIntermNode* HlslParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* ex
     return switchNode;
 }
 
-// Track levels of class/struct nesting with a prefix string using
+// Track levels of class/struct/namespace nesting with a prefix string using
 // the type names separated by the scoping operator. E.g., two levels
 // would look like:
 //
@@ -7093,41 +7093,43 @@ TIntermNode* HlslParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* ex
 //
 // The string is empty when at normal global level.
 //
-void HlslParseContext::pushThis(const TString& typeName)
+void HlslParseContext::pushNamespace(const TString& typeName)
 {
     // make new type prefix
     TString newPrefix;
     if (currentTypePrefix.size() > 0) {
         newPrefix = currentTypePrefix.back();
-        newPrefix.append("::");
+        newPrefix.append(scopeMangler);
     }
     newPrefix.append(typeName);
     currentTypePrefix.push_back(newPrefix);
 }
 
-// Opposite of pushThis(), see above
-void HlslParseContext::popThis()
+// Opposite of pushNamespace(), see above
+void HlslParseContext::popNamespace()
 {
     currentTypePrefix.pop_back();
 }
 
 // Use the class/struct nesting string to create a global name for
-// a member of a class/struct.  Static members use "::" for the final
-// step, while non-static members use ".".
-TString* HlslParseContext::getFullMemberFunctionName(const TString& memberName, bool isStatic) const
+// a member of a class/struct.
+TString* HlslParseContext::getFullNamespaceName(const TString& localName) const
 {
     TString* name = NewPoolTString("");
     if (currentTypePrefix.size() > 0)
         name->append(currentTypePrefix.back());
-    if (isStatic)
-        name->append("::");
-    else
-        name->append(".");
-    name->append(memberName);
+    name->append(scopeMangler);
+    name->append(localName);
 
     return name;
 }
 
+// Helper function to add the namespace scope mangling syntax to a string.
+void HlslParseContext::addScopeMangler(TString& name)
+{
+    name.append(scopeMangler);
+}
+
 // Potentially rename shader entry point function
 void HlslParseContext::renameShaderFunction(TString*& name) const
 {
index 602bb86acfec597fd7ba6e3d687666e427e15da3..904ec0f89fede652bf83fbe83dab79760f8e00b2 100755 (executable)
@@ -160,9 +160,10 @@ public:
     void pushScope()         { symbolTable.push(); }
     void popScope()          { symbolTable.pop(0); }
 
-    void pushThis(const TString& name);
-    void popThis();
-    TString* getFullMemberFunctionName(const TString& name, bool isStatic) const;
+    void pushNamespace(const TString& name);
+    void popNamespace();
+    TString* getFullNamespaceName(const TString& localName) const;
+    void addScopeMangler(TString&);
 
     void pushSwitchSequence(TIntermSequence* sequence) { switchSequenceStack.push_back(sequence); }
     void popSwitchSequence() { switchSequenceStack.pop_back(); }