void DumpTree::visit(Assignment &assign)
{
- append(format("Assignment: %s%s", assign.oper->token, (assign.self_referencing ? " (self-referencing)" : "")));
+ append(format("Assignment: %s%s -> %s", assign.oper->token, (assign.self_referencing ? " (self-referencing)" : ""), format_type(assign.type)));
begin_sub();
if(assign.target_declaration)
append(format("Target: %%%d %s %s", get_label(*assign.target_declaration), assign.target_declaration->type, assign.target_declaration->name));
resolve(unary, basic, unary.expression->lvalue);
}
-void ExpressionResolver::visit(BinaryExpression &binary)
+void ExpressionResolver::visit(BinaryExpression &binary, bool assign)
{
- TraversingVisitor::visit(binary);
-
/* Binary operators are only defined for basic types (not for image or
structure types). */
BasicTypeDeclaration *basic_left = dynamic_cast<BasicTypeDeclaration *>(binary.left->type);
Compatibility elem_compat = get_compatibility(*elem_left, *elem_right);
if(elem_compat==NOT_COMPATIBLE)
return;
+ if(assign && (compat==LEFT_CONVERTIBLE || elem_compat==LEFT_CONVERTIBLE))
+ return;
TypeDeclaration *type = 0;
char oper2 = binary.oper->token[1];
else
return;
+ if(assign && type!=basic_left)
+ return;
+
bool converted = true;
if(compat==LEFT_CONVERTIBLE)
convert_to(binary.left, *basic_right);
if(!converted)
type = 0;
- resolve(binary, type, false);
+ resolve(binary, type, assign);
+}
+
+void ExpressionResolver::visit(BinaryExpression &binary)
+{
+ TraversingVisitor::visit(binary);
+ visit(binary, false);
}
void ExpressionResolver::visit(Assignment &assign)
{
TraversingVisitor::visit(assign);
+
+ if(assign.oper->token[0]!='=')
+ return visit(assign, true);
+ else if(assign.left->type!=assign.right->type)
+ {
+ BasicTypeDeclaration *basic_left = dynamic_cast<BasicTypeDeclaration *>(assign.left->type);
+ BasicTypeDeclaration *basic_right = dynamic_cast<BasicTypeDeclaration *>(assign.right->type);
+ if(!basic_left || !basic_right)
+ return;
+
+ Compatibility compat = get_compatibility(*basic_left, *basic_right);
+ if(compat==RIGHT_CONVERTIBLE)
+ convert_to(assign.right, *basic_left);
+ else if(compat!=SAME_TYPE)
+ return;
+ }
+
resolve(assign, assign.left->type, true);
}
virtual void visit(InterfaceBlockReference &);
virtual void visit(MemberAccess &);
virtual void visit(UnaryExpression &);
+ void visit(BinaryExpression &, bool);
virtual void visit(BinaryExpression &);
virtual void visit(Assignment &);
virtual void visit(FunctionCall &);
+#include <cstring>
#include <msp/core/raii.h>
#include <msp/strings/format.h>
#include "validate.h"
void ExpressionValidator::visit(Assignment &assign)
{
- if(assign.left->type && !assign.left->lvalue)
- error(assign, "Target of assignment is not an lvalue");
- if(assign.left->type && assign.right->type && assign.left->type!=assign.right->type)
- error(assign, format("Assignment to variable of type '%s' from expression of type '%s'",
- assign.left->type->name, assign.right->type->name));
+ if(assign.left->type)
+ {
+ if(!assign.left->lvalue)
+ error(assign, "Target of assignment is not an lvalue");
+ if(assign.right->type)
+ {
+ if(assign.oper->token[0]!='=')
+ {
+ if(!assign.type)
+ error(assign, format("No matching operator '%s' found for '%s' and '%s'",
+ string(assign.oper->token, strlen(assign.oper->token)-1), assign.left->type->name, assign.right->type->name));
+ }
+ else if(assign.left->type!=assign.right->type)
+ error(assign, format("Assignment to variable of type '%s' from expression of incompatible type '%s'",
+ assign.left->type->name, assign.right->type->name));
+ }
+ }
TraversingVisitor::visit(assign);
}
void ExpressionValidator::visit(VariableDeclaration &var)
{
if(var.init_expression && var.init_expression->type && var.type_declaration && var.init_expression->type!=var.type_declaration)
- error(var, format("Initializing a variable of type '%s' with an expression of type '%s'",
+ error(var, format("Initializing a variable of type '%s' with an expression of incompatible type '%s'",
var.type_declaration->name, var.init_expression->type->name));
TraversingVisitor::visit(var);
}
--- /dev/null
+uniform mat4 mvp;
+uniform sampler2D tex;
+uniform vec3 tint;
+uniform vec3 ambient;
+
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+layout(location=1) in vec3 normal;
+layout(location=2) in vec2 texcoord;
+void main()
+{
+ out float light = normal.z;
+ passthrough;
+ gl_Position = mvp*position;
+}
+
+#pragma MSP stage(fragment)
+out vec4 frag_color;
+void main()
+{
+ vec3 color = texture(tex, texcoord);
+ color *= tint;
+ color *= light;
+ color += ambient;
+ frag_color = vec4(color, 1.0);
+}
+
+/* Expected output: vertex
+uniform mat4 mvp;
+layout(location=0) in vec4 position;
+layout(location=1) in vec3 normal;
+layout(location=2) in vec2 texcoord;
+out float light;
+out vec2 _vs_out_texcoord;
+void main()
+{
+ light = normal.z;
+ _vs_out_texcoord = texcoord;
+ gl_Position = mvp*position;
+}
+*/
+
+/* Expected output: fragment
+uniform sampler2D tex;
+uniform vec3 tint;
+uniform vec3 ambient;
+out vec4 frag_color;
+in vec2 _vs_out_texcoord;
+in float light;
+void main()
+{
+ vec3 color = texture(tex, _vs_out_texcoord);
+ color *= tint;
+ color *= light;
+ color += ambient;
+ frag_color = vec4(color, 1.0);
+}
+*/
int i = 0;
i = i-3;
float f = 0;
+ f = i+1;
f = (f+i)*(f/i);
bool b = i<f || i>=f;
b = b && i==f;
{
int i = 0;
i = i-3;
- float f = float(0);
+ float f;
+ f = float(i+1);
f = (f+float(i))*(f/float(i));
bool b = float(i)<f||float(i)>=f;
b = b&&float(i)==f;
int i = 1.0;
bool b = 0;
i = b;
+ i *= b;
float f = b;
- i+b;
+ f+b;
+ i /= f;
mat3x2 m;
vec3 v;
m*m;
}
/* Expected error:
-<test>:4: Initializing a variable of type 'int' with an expression of type 'float'
-<test>:5: Initializing a variable of type 'bool' with an expression of type 'int'
-<test>:6: Assignment to variable of type 'int' from expression of type 'bool'
-<test>:7: Initializing a variable of type 'float' with an expression of type 'bool'
-<test>:8: No matching operator '+' found for 'int' and 'bool'
-<test>:11: No matching operator '*' found for 'mat3x2' and 'mat3x2'
-<test>:12: No matching operator '*' found for 'vec3' and 'mat3x2'
+<test>:4: Initializing a variable of type 'int' with an expression of incompatible type 'float'
+<test>:5: Initializing a variable of type 'bool' with an expression of incompatible type 'int'
+<test>:6: Assignment to variable of type 'int' from expression of incompatible type 'bool'
+<test>:7: No matching operator '*' found for 'int' and 'bool'
+<test>:8: Initializing a variable of type 'float' with an expression of incompatible type 'bool'
+<test>:9: No matching operator '+' found for 'float' and 'bool'
+<test>:10: No matching operator '/' found for 'int' and 'float'
+<test>:13: No matching operator '*' found for 'mat3x2' and 'mat3x2'
+<test>:14: No matching operator '*' found for 'vec3' and 'mat3x2'
*/