Implemented function prototyping and in/out parameters
TRAC #11725
Signed-off-by: Shannon Woods
Signed-off-by: Daniel Koch

Author:    Nicolas Capens

git-svn-id: https://angleproject.googlecode.com/svn/trunk@120 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/OutputHLSL.cpp b/src/compiler/OutputHLSL.cpp
index 9875f0a..fdb7f49 100644
--- a/src/compiler/OutputHLSL.cpp
+++ b/src/compiler/OutputHLSL.cpp
@@ -870,6 +870,34 @@
             out << ", ";
         }
         break;
+      case EOpPrototype:
+        if (visit == PreVisit)
+        {
+            out << typeString(node->getType()) << " " << node->getName() << "(";
+
+            TIntermSequence &arguments = node->getSequence();
+
+            for (unsigned int i = 0; i < arguments.size(); i++)
+            {
+                TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
+
+                if (symbol)
+                {
+                    out << argumentString(symbol);
+
+                    if (i < arguments.size() - 1)
+                    {
+                        out << ", ";
+                    }
+                }
+                else UNREACHABLE();
+            }
+
+            out << ");\n";
+
+            return false;
+        }
+        break;
       case EOpComma:         UNIMPLEMENTED(); /* FIXME */ out << "Comma\n"; return true;
       case EOpFunction:
         {
@@ -893,10 +921,7 @@
 
                     if (symbol)
                     {
-                        const TType &type = symbol->getType();
-                        const TString &name = symbol->getSymbol();
-
-                        out << typeString(type) + " " + name;
+                        out << argumentString(symbol);
 
                         if (i < arguments.size() - 1)
                         {
@@ -1477,6 +1502,29 @@
     }
 }
 
+TString OutputHLSL::argumentString(const TIntermSymbol *symbol)
+{
+    TQualifier qualifier = symbol->getQualifier();
+    const TType &type = symbol->getType();
+    const TString &name = symbol->getSymbol();
+
+    return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type);
+}
+
+TString OutputHLSL::qualifierString(TQualifier qualifier)
+{
+    switch(qualifier)
+    {
+      case EvqIn:            return "in";
+      case EvqOut:           return "out";
+      case EvqInOut:         return "inout";
+      case EvqConstReadOnly: return "const";
+      default: UNREACHABLE();
+    }
+
+    return "";
+}
+
 TString OutputHLSL::typeString(const TType &type)
 {
     if (type.getBasicType() == EbtStruct)
diff --git a/src/compiler/OutputHLSL.h b/src/compiler/OutputHLSL.h
index fcb9488..ccd1fe5 100644
--- a/src/compiler/OutputHLSL.h
+++ b/src/compiler/OutputHLSL.h
@@ -33,6 +33,8 @@
     bool handleExcessiveLoop(TIntermLoop *node);
     void outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString);
 
+    static TString argumentString(const TIntermSymbol *symbol);
+    static TString qualifierString(TQualifier qualifier);
     static TString typeString(const TType &type);
     static TString arrayString(const TType &type);
     static TString initializer(const TType &type);
diff --git a/src/compiler/glslang.y b/src/compiler/glslang.y
index 07f9e0e..73d5d56 100644
--- a/src/compiler/glslang.y
+++ b/src/compiler/glslang.y
@@ -985,7 +985,31 @@
     ;
 
 declaration
-    : function_prototype SEMICOLON   { $$ = 0; }
+    : function_prototype SEMICOLON   {
+        TFunction &function = *($1.function);
+        
+        TIntermAggregate *prototype = new TIntermAggregate;
+        prototype->setType(function.getReturnType());
+        prototype->setName(function.getName());
+        
+        for (int i = 0; i < function.getParamCount(); i++)
+        {
+            TParameter &param = function[i];
+            if (param.name != 0)
+            {
+                TVariable *variable = new TVariable(param.name, *param.type);
+                
+                prototype = parseContext->intermediate.growAggregate(prototype, parseContext->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), $1.line), $1.line);
+            }
+            else
+            {
+                prototype = parseContext->intermediate.growAggregate(prototype, parseContext->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line);
+            }
+        }
+        
+        prototype->setOperator(EOpPrototype);
+        $$ = prototype;
+    }
     | init_declarator_list SEMICOLON {
 		if ($1.intermAggregate)
             $1.intermAggregate->setOperator(EOpDeclaration);
diff --git a/src/compiler/intermediate.h b/src/compiler/intermediate.h
index 4f83b86..47cfc10 100644
--- a/src/compiler/intermediate.h
+++ b/src/compiler/intermediate.h
@@ -29,7 +29,9 @@
     EOpFunctionCall,    
     EOpFunction,        // For function definition
     EOpParameters,      // an aggregate listing the parameters to a function
+
     EOpDeclaration,
+    EOpPrototype,
 
     //
     // Unary operators