]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/validate.cpp
Implement the ternary operator in GLSL
[libs/gl.git] / source / glsl / validate.cpp
index 91d1de991515dc74dbb359d0385a0429ef855803..6e90698c97b500c5dd2edcaebd7e3f8c70e90026 100644 (file)
@@ -2,6 +2,7 @@
 #include <cstring>
 #include <msp/core/raii.h>
 #include <msp/strings/format.h>
+#include <msp/strings/utils.h>
 #include "validate.h"
 
 using namespace std;
@@ -236,6 +237,32 @@ void ReferenceValidator::visit(InterfaceBlockReference &iface)
                error(iface, format("Use of unlinked input block '%s'", iface.name));
 }
 
+void ReferenceValidator::visit(FunctionCall &call)
+{
+       if(!call.declaration && !call.constructor)
+       {
+               map<string, FunctionDeclaration *>::iterator i = stage->functions.lower_bound(call.name);
+               if(i!=stage->functions.end() && i->second->name==call.name)
+               {
+                       bool valid_types = true;
+                       string signature;
+                       for(NodeArray<Expression>::const_iterator j=call.arguments.begin(); (valid_types && j!=call.arguments.end()); ++j)
+                       {
+                               if((*j)->type)
+                                       append(signature, ", ", (*j)->type->name);
+                               else
+                                       valid_types = false;
+                       }
+
+                       if(valid_types)
+                               error(call, format("No matching overload found for call to '%s(%s)'", call.name, signature));
+               }
+               else
+                       error(call, format("Call to undeclared function '%s'", call.name));
+       }
+       TraversingVisitor::visit(call);
+}
+
 void ReferenceValidator::visit(VariableDeclaration &var)
 {
        if(!var.type_declaration)
@@ -338,6 +365,20 @@ void ExpressionValidator::visit(Assignment &assign)
        TraversingVisitor::visit(assign);
 }
 
+void ExpressionValidator::visit(TernaryExpression &ternary)
+{
+       if(ternary.condition->type)
+       {
+               BasicTypeDeclaration *basic_cond = dynamic_cast<BasicTypeDeclaration *>(ternary.condition->type);
+               if(!basic_cond || basic_cond->kind!=BasicTypeDeclaration::BOOL)
+                       error(ternary, "Ternary operator condition is not a boolean");
+               else if(!ternary.type && ternary.true_expr->type && ternary.false_expr->type)
+                       error(ternary, format("Ternary operator has incompatible types '%s' and '%s'",
+                               ternary.true_expr->type->name, ternary.false_expr->type->name));
+       }
+       TraversingVisitor::visit(ternary);
+}
+
 void ExpressionValidator::visit(VariableDeclaration &var)
 {
        if(var.init_expression && var.init_expression->type && var.type_declaration && var.init_expression->type!=var.type_declaration)