Do not write extraneous semi-colons - some glsl compilers are do not like that even though it is so easy to ignore.
Review URL: http://codereview.appspot.com/1301041

git-svn-id: https://angleproject.googlecode.com/svn/trunk@317 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/OutputGLSL.cpp b/src/compiler/OutputGLSL.cpp
index 936d1bb..1b3c13a 100644
--- a/src/compiler/OutputGLSL.cpp
+++ b/src/compiler/OutputGLSL.cpp
@@ -46,12 +46,30 @@
     out << "[" << type.getArraySize() << "]";
     return TString(out.c_str());
 }
+
+bool isSingleStatement(TIntermNode* node) {
+    const TIntermAggregate* aggregate = node->getAsAggregate();
+    if (aggregate != NULL)
+    {
+        if ((aggregate->getOp() == EOpFunction) ||
+            (aggregate->getOp() == EOpSequence))
+            return false;
+    }
+    else if (node->getAsSelectionNode() != NULL)
+    {
+        return false;
+    }
+    else if (node->getAsLoopNode() != NULL)
+    {
+        return false;
+    }
+    return true;
+}
 }  // namespace
 
 TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink)
     : TIntermTraverser(true, true, true),
       mObjSink(objSink),
-      mScopeSequences(false),
       mDeclaringVariables(false)
 {
 }
@@ -390,23 +408,17 @@
     {
         out << "if (";
         node->getCondition()->traverse(this);
-        out << ") {\n";
+        out << ")\n";
 
         incrementDepth();
-        if (node->getTrueBlock())
-        {
-            node->getTrueBlock()->traverse(this);
-        }
-        out << ";\n}";
+        visitCodeBlock(node->getTrueBlock());
 
         if (node->getFalseBlock())
         {
-            out << " else {\n";
-            node->getFalseBlock()->traverse(this);
-            out << ";\n}";
+            out << "else\n";
+            visitCodeBlock(node->getFalseBlock());
         }
         decrementDepth();
-        out << "\n";
     }
     return false;
 }
@@ -417,23 +429,29 @@
     TInfoSinkBase& out = objSink();
     switch (node->getOp())
     {
-        case EOpSequence:
-            if (visit == PreVisit)
+        case EOpSequence: {
+            // Scope the sequences except when at the global scope.
+            if (depth > 0) out << "{\n";
+
+            incrementDepth();
+            const TIntermSequence& sequence = node->getSequence();
+            for (TIntermSequence::const_iterator iter = sequence.begin();
+                 iter != sequence.end(); ++iter)
             {
-                if (mScopeSequences)
-                    out << "{\n";
+                TIntermNode* node = *iter;
+                ASSERT(node != NULL);
+                node->traverse(this);
+
+                if (isSingleStatement(node))
+                    out << ";\n";
             }
-            else if (visit == InVisit)
-            {
-                out << ";\n";
-            }
-            else if (visit == PostVisit)
-            {
-                out << ";\n";
-                if (mScopeSequences)
-                    out << "}\n";
-            }
+            decrementDepth();
+
+            // Scope the sequences except when at the global scope.
+            if (depth > 0) out << "}\n";
+            visitChildren = false;
             break;
+        }
         case EOpPrototype: {
             // Function declaration.
             ASSERT(visit == PreVisit);
@@ -454,6 +472,7 @@
             TString functionName = TFunction::unmangleName(node->getName());
             out << returnType << " " << functionName;
 
+            incrementDepth();
             // Function definition node contains one or two children nodes
             // representing function parameters and function body. The latter
             // is not present in case of empty function bodies.
@@ -470,20 +489,8 @@
             // Traverse function body.
             TIntermAggregate* body = ++seqIter != sequence.end() ?
                 (*seqIter)->getAsAggregate() : NULL;
-            if (body != NULL)
-            {
-                ASSERT(body->getOp() == EOpSequence);
-                // Sequences are scoped with {} inside function body so that
-                // variables are declared in the correct scope.
-                mScopeSequences = true;
-                body->traverse(this);
-                mScopeSequences = false;
-            }
-            else
-            {
-                // Empty function body.
-                out << "{}\n";
-            }
+            visitCodeBlock(body);
+            decrementDepth();
  
             // Fully processed; no need to visit children.
             visitChildren = false;
@@ -602,6 +609,7 @@
 {
     TInfoSinkBase& out = objSink();
 
+    incrementDepth();
     // Loop header.
     if (node->testFirst())  // for loop
     {
@@ -616,29 +624,25 @@
 
         if (node->getTerminal())
             node->getTerminal()->traverse(this);
-        out << ") {\n";
+        out << ")\n";
     }
     else  // do-while loop
     {
-        out << "do {\n";
+        out << "do\n";
     }
 
     // Loop body.
-    if (node->getBody())
-        node->getBody()->traverse(this);
+    visitCodeBlock(node->getBody());
 
     // Loop footer.
-    if (node->testFirst())  // for loop
+    if (!node->testFirst())  // while loop
     {
-        out << "}\n";
-    }
-    else  // do-while loop
-    {
-        out << "} while (";
+        out << "while (";
         ASSERT(node->getTest() != NULL);
         node->getTest()->traverse(this);
         out << ");\n";
     }
+    decrementDepth();
 
     // No need to visit children. They have been already processed in
     // this function.
@@ -660,3 +664,19 @@
 
     return true;
 }
+
+void TOutputGLSL::visitCodeBlock(TIntermNode* node) {
+    TInfoSinkBase &out = objSink();
+    if (node != NULL)
+    {
+        node->traverse(this);
+        // Single statements not part of a sequence need to be terminated
+        // with semi-colon.
+        if (isSingleStatement(node))
+            out << ";\n";
+    }
+    else
+    {
+        out << "{\n}\n";  // Empty code block.
+    }
+}