3 #include <msp/core/raii.h>
4 #include <msp/strings/format.h>
5 #include <msp/strings/utils.h>
14 Validator::Validator():
19 void Validator::diagnose(Node &node, Node &provoking_node, Diagnostic::Severity severity, const string &message)
22 diag.severity = severity;
23 diag.source = node.source;
24 diag.line = node.line;
25 diag.provoking_source = provoking_node.source;
26 diag.provoking_line = provoking_node.line;
27 diag.message = message;
28 stage->diagnostics.push_back(diag);
30 last_provoker = &provoking_node;
33 void Validator::add_info(Node &node, const string &message)
36 throw logic_error("Tried to add info without a previous provoker");
37 diagnose(node, *last_provoker, Diagnostic::INFO, message);
41 TypeValidator::TypeValidator():
45 void TypeValidator::visit(BasicTypeDeclaration &type)
47 if(type.kind==BasicTypeDeclaration::VECTOR)
49 BasicTypeDeclaration::Kind base_kind = BasicTypeDeclaration::VOID;
50 if(BasicTypeDeclaration *basic_base = dynamic_cast<BasicTypeDeclaration *>(type.base_type))
51 base_kind = basic_base->kind;
52 if(base_kind!=BasicTypeDeclaration::BOOL && base_kind!=BasicTypeDeclaration::INT && base_kind!=BasicTypeDeclaration::FLOAT)
53 error(type, format("Invalid base type '%s' for vector type '%s'", type.base, type.name));
55 else if(type.kind==BasicTypeDeclaration::ARRAY)
57 if(BasicTypeDeclaration *basic_base = dynamic_cast<BasicTypeDeclaration *>(type.base_type))
58 if(basic_base->kind==BasicTypeDeclaration::VOID)
59 error(type, format("Invalid base type '%s' for array type '%s'", type.base, type.name));
63 void TypeValidator::visit(ImageTypeDeclaration &type)
65 BasicTypeDeclaration::Kind base_kind = BasicTypeDeclaration::VOID;
66 if(BasicTypeDeclaration *basic_base = dynamic_cast<BasicTypeDeclaration *>(type.base_type))
67 base_kind = basic_base->kind;
68 if(base_kind!=BasicTypeDeclaration::INT && base_kind!=BasicTypeDeclaration::FLOAT)
69 error(type, format("Invalid base type '%s' for image type '%s'", type.base, type.name));
72 void TypeValidator::visit(StructDeclaration &strct)
74 SetFlag set_struct(in_struct);
75 TraversingVisitor::visit(strct);
78 void TypeValidator::visit(VariableDeclaration &var)
83 error(var, "Struct members can't have layouts");
84 if(var.init_expression)
85 error(var, "Struct members can't have initializers");
88 TraversingVisitor::visit(var);
92 DeclarationValidator::DeclarationValidator():
93 anonymous_block(false)
96 void DeclarationValidator::multiple_definition(const string &name, Statement &statement, Statement &previous)
98 error(statement, format("Multiple definition of %s", name));
99 add_info(previous, "Previous definition is here");
102 Statement *DeclarationValidator::find_definition(const string &name)
104 BlockDeclarationMap *decls = &declarations[current_block];
105 BlockDeclarationMap::const_iterator i = decls->find(name);
106 if(i==decls->end() && anonymous_block)
108 decls = &declarations[current_block->parent];
109 i = decls->find(name);
111 return (i!=decls->end() ? i->second : 0);
114 void DeclarationValidator::check_definition(const string &name, Statement &statement)
116 if(Statement *previous = find_definition(name))
117 multiple_definition(format("'%s'", name), statement, *previous);
119 record_definition(name, statement);
122 void DeclarationValidator::record_definition(const string &name, Statement &statement)
124 declarations[current_block].insert(make_pair(name, &statement));
126 declarations[current_block->parent].insert(make_pair(name, &statement));
129 void DeclarationValidator::visit(TypeDeclaration &type)
131 check_definition(type.name, type);
134 void DeclarationValidator::visit(StructDeclaration &strct)
136 check_definition(strct.name, strct);
137 TraversingVisitor::visit(strct);
140 void DeclarationValidator::visit(VariableDeclaration &var)
142 check_definition(var.name, var);
143 TraversingVisitor::visit(var);
146 void DeclarationValidator::visit(InterfaceBlock &iface)
148 string key = iface.interface+iface.name;
149 map<string, InterfaceBlock *>::const_iterator i = interface_blocks.find(key);
150 if(i!=interface_blocks.end())
151 multiple_definition(format("interface block '%s %s'", iface.interface, iface.name), iface, *i->second);
153 interface_blocks.insert(make_pair(key, &iface));
155 if(Statement *previous = find_definition(iface.name))
157 if(!dynamic_cast<InterfaceBlock *>(previous))
158 multiple_definition(format("'%s'", iface.name), iface, *previous);
161 record_definition(iface.name, iface);
163 if(!iface.instance_name.empty())
164 check_definition(iface.instance_name, iface);
166 if(iface.instance_name.empty() && iface.struct_declaration)
168 // Inject anonymous interface block members into the global scope
169 const map<string, VariableDeclaration *> &iface_vars = iface.struct_declaration->members.variables;
170 for(map<string, VariableDeclaration *>::const_iterator j=iface_vars.begin(); j!=iface_vars.end(); ++j)
171 check_definition(j->first, *j->second);
175 void DeclarationValidator::visit(FunctionDeclaration &func)
177 string key = func.name+func.signature;
178 map<string, FunctionDeclaration *>::const_iterator i = overloaded_functions.find(key);
179 if(i==overloaded_functions.end())
180 overloaded_functions.insert(make_pair(key, &func));
181 else if(func.return_type_declaration && i->second->return_type_declaration!=func.return_type_declaration)
183 error(func, format("Conflicting return type '%s' for function '%s'", func.return_type_declaration->name, func.name));
184 if(i->second->return_type_declaration)
185 add_info(*i->second, format("Previously declared as returning '%s'", i->second->return_type_declaration->name));
188 if(Statement *previous = find_definition(func.name))
190 if(!dynamic_cast<FunctionDeclaration *>(previous))
191 multiple_definition(format("'%s'", func.name), func, *previous);
194 record_definition(func.name, func);
196 if(func.definition==&func)
197 check_definition(func.name+func.signature, func);
199 TraversingVisitor::visit(func);
203 void ReferenceValidator::visit(BasicTypeDeclaration &type)
205 if(!type.base.empty() && !type.base_type)
206 error(type, format("Use of undeclared type '%s'", type.base));
209 void ReferenceValidator::visit(ImageTypeDeclaration &type)
211 if(!type.base.empty() && !type.base_type)
212 error(type, format("Use of undeclared type '%s'", type.base));
215 void ReferenceValidator::visit(VariableReference &var)
218 error(var, format("Use of undeclared variable '%s'", var.name));
219 else if(stage->type!=Stage::VERTEX && var.declaration->interface=="in" && var.name.compare(0, 3, "gl_") && !var.declaration->linked_declaration)
220 error(var, format("Use of unlinked input variable '%s'", var.name));
223 void ReferenceValidator::visit(MemberAccess &memacc)
225 if(memacc.left->type && !memacc.declaration)
226 error(memacc, format("Use of undeclared member '%s'", memacc.member));
227 TraversingVisitor::visit(memacc);
230 void ReferenceValidator::visit(InterfaceBlockReference &iface)
232 /* An interface block reference without a declaration should be impossible
233 since references are generated based on existing declarations. */
234 if(!iface.declaration)
235 error(iface, format("Use of undeclared interface block '%s'", iface.name));
236 else if(stage->type!=Stage::VERTEX && iface.declaration->interface=="in" && !iface.declaration->linked_block)
237 error(iface, format("Use of unlinked input block '%s'", iface.name));
240 void ReferenceValidator::visit(FunctionCall &call)
242 if((!call.constructor && !call.declaration) || (call.constructor && !call.type))
244 bool have_declaration = call.constructor;
245 if(!call.constructor)
247 map<string, FunctionDeclaration *>::iterator i = stage->functions.lower_bound(call.name);
248 have_declaration = (i!=stage->functions.end() && i->second->name==call.name);
253 bool valid_types = true;
255 for(NodeArray<Expression>::const_iterator j=call.arguments.begin(); (valid_types && j!=call.arguments.end()); ++j)
258 append(signature, ", ", (*j)->type->name);
264 error(call, format("No matching %s found for '%s(%s)'", (call.constructor ? "constructor" : "overload"), call.name, signature));
267 error(call, format("Call to undeclared function '%s'", call.name));
269 TraversingVisitor::visit(call);
272 void ReferenceValidator::visit(VariableDeclaration &var)
274 if(!var.type_declaration)
275 error(var, format("Use of undeclared type '%s'", var.type));
276 TraversingVisitor::visit(var);
279 void ReferenceValidator::visit(InterfaceBlock &iface)
281 if(!iface.struct_declaration)
282 error(iface, format("Interface block '%s %s' lacks a struct declaration", iface.interface, iface.name));
283 TraversingVisitor::visit(iface);
286 void ReferenceValidator::visit(FunctionDeclaration &func)
288 if(!func.return_type_declaration)
289 error(func, format("Use of undeclared type '%s'", func.return_type));
290 TraversingVisitor::visit(func);
294 void ExpressionValidator::visit(Swizzle &swizzle)
297 if(BasicTypeDeclaration *basic = dynamic_cast<BasicTypeDeclaration *>(swizzle.left->type))
299 if(basic->kind==BasicTypeDeclaration::INT || basic->kind==BasicTypeDeclaration::FLOAT)
301 else if(basic->kind==BasicTypeDeclaration::VECTOR)
307 static const char component_names[] = { 'x', 'y', 'z', 'w', 'r', 'g', 'b', 'a', 's', 't', 'p', 'q' };
309 for(unsigned i=0; i<swizzle.count; ++i)
311 unsigned component_flavour = (find(component_names, component_names+12, swizzle.component_group[i])-component_names)/4;
313 flavour = component_flavour;
314 else if(flavour>=0 && component_flavour!=static_cast<unsigned>(flavour))
316 error(swizzle, format("Flavour of swizzle component '%c' is inconsistent with '%c'",
317 swizzle.component_group[i], swizzle.component_group[0]));
321 if(swizzle.components[i]>=size)
322 error(swizzle, format("Access to component '%c' which is not present in '%s'",
323 swizzle.component_group[i], swizzle.left->type->name));
326 else if(swizzle.left->type)
327 error(swizzle, format("Swizzle applied to '%s' which is neither a scalar nor a vector", swizzle.left->type->name));
329 TraversingVisitor::visit(swizzle);
332 void ExpressionValidator::visit(UnaryExpression &unary)
334 if(unary.expression->type)
337 error(unary, format("No matching operator '%s' found for '%s'", unary.oper->token, unary.expression->type->name));
338 else if((unary.oper->token[1]=='+' || unary.oper->token[1]=='-') && !unary.expression->lvalue)
339 error(unary, format("Operand of '%s' is not an lvalue", unary.oper->token));
341 TraversingVisitor::visit(unary);
344 void ExpressionValidator::visit(BinaryExpression &binary)
346 if(!binary.type && binary.left->type && binary.right->type)
348 if(binary.oper->token[0]=='[')
349 error(binary, format("Can't index element of '%s' with '%s'",
350 binary.left->type->name, binary.right->type->name));
352 error(binary, format("No matching operator '%s' found for '%s' and '%s'",
353 binary.oper->token, binary.left->type->name, binary.right->type->name));
355 TraversingVisitor::visit(binary);
358 void ExpressionValidator::visit(Assignment &assign)
360 if(assign.left->type)
362 if(!assign.left->lvalue)
363 error(assign, "Target of assignment is not an lvalue");
364 if(assign.right->type)
366 if(assign.oper->token[0]!='=')
369 error(assign, format("No matching operator '%s' found for '%s' and '%s'",
370 string(assign.oper->token, strlen(assign.oper->token)-1), assign.left->type->name, assign.right->type->name));
372 else if(assign.left->type!=assign.right->type)
373 error(assign, format("Assignment to variable of type '%s' from expression of incompatible type '%s'",
374 assign.left->type->name, assign.right->type->name));
377 TraversingVisitor::visit(assign);
380 void ExpressionValidator::visit(TernaryExpression &ternary)
382 if(ternary.condition->type)
384 BasicTypeDeclaration *basic_cond = dynamic_cast<BasicTypeDeclaration *>(ternary.condition->type);
385 if(!basic_cond || basic_cond->kind!=BasicTypeDeclaration::BOOL)
386 error(ternary, "Ternary operator condition is not a boolean");
387 else if(!ternary.type && ternary.true_expr->type && ternary.false_expr->type)
388 error(ternary, format("Ternary operator has incompatible types '%s' and '%s'",
389 ternary.true_expr->type->name, ternary.false_expr->type->name));
391 TraversingVisitor::visit(ternary);
394 void ExpressionValidator::visit(VariableDeclaration &var)
396 if(var.init_expression && var.init_expression->type && var.type_declaration && var.init_expression->type!=var.type_declaration)
397 error(var, format("Initializing a variable of type '%s' with an expression of incompatible type '%s'",
398 var.type_declaration->name, var.init_expression->type->name));
399 TraversingVisitor::visit(var);