]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/validate.cpp
Give declaration nodes to all GLSL types.
[libs/gl.git] / source / glsl / validate.cpp
1 #include <msp/core/raii.h>
2 #include <msp/strings/format.h>
3 #include "validate.h"
4
5 using namespace std;
6
7 namespace Msp {
8 namespace GL {
9 namespace SL {
10
11 Validator::Validator():
12         stage(0)
13 { }
14
15 void Validator::diagnose(Node &node, Diagnostic::Severity severity, const string &message)
16 {
17         Diagnostic diag;
18         diag.severity = severity;
19         diag.source = node.source;
20         diag.line = node.line;
21         diag.message = message;
22         stage->diagnostics.push_back(diag);
23 }
24
25
26 DeclarationValidator::DeclarationValidator():
27         anonymous_block(false)
28 { }
29
30 void DeclarationValidator::multiple_definition(const string &name, Statement &statement, Statement &previous)
31 {
32         error(statement, format("Multiple definition of %s", name));
33         diagnose(previous, Diagnostic::INFO, "Previous definition is here");
34 }
35
36 Statement *DeclarationValidator::find_definition(const string &name)
37 {
38         BlockDeclarationMap *decls = &declarations[current_block];
39         BlockDeclarationMap::const_iterator i = decls->find(name);
40         if(i==decls->end() && anonymous_block)
41         {
42                 decls = &declarations[current_block->parent];
43                 i = decls->find(name);
44         }
45         return (i!=decls->end() ? i->second : 0);
46 }
47
48 void DeclarationValidator::check_definition(const string &name, Statement &statement)
49 {
50         if(Statement *previous = find_definition(name))
51                 multiple_definition(format("'%s'", name), statement, *previous);
52         else
53                 record_definition(name, statement);
54 }
55
56 void DeclarationValidator::record_definition(const string &name, Statement &statement)
57 {
58         declarations[current_block].insert(make_pair(name, &statement));
59         if(anonymous_block)
60                 declarations[current_block->parent].insert(make_pair(name, &statement));
61 }
62
63 void DeclarationValidator::visit(TypeDeclaration &type)
64 {
65         check_definition(type.name, type);
66 }
67
68 void DeclarationValidator::visit(StructDeclaration &strct)
69 {
70         check_definition(strct.name, strct);
71         TraversingVisitor::visit(strct);
72 }
73
74 void DeclarationValidator::visit(VariableDeclaration &var)
75 {
76         check_definition(var.name, var);
77         TraversingVisitor::visit(var);
78 }
79
80 void DeclarationValidator::visit(InterfaceBlock &iface)
81 {
82         string key = iface.interface+iface.name;
83         map<string, InterfaceBlock *>::const_iterator i = interface_blocks.find(key);
84         if(i!=interface_blocks.end())
85                 multiple_definition(format("interface block '%s %s'", iface.interface, iface.name), iface, *i->second);
86         else
87                 interface_blocks.insert(make_pair(key, &iface));
88
89         if(Statement *previous = find_definition(iface.name))
90         {
91                 if(!dynamic_cast<InterfaceBlock *>(previous))
92                         multiple_definition(format("'%s'", iface.name), iface, *previous);
93         }
94         else
95                 record_definition(iface.name, iface);
96
97         if(!iface.instance_name.empty())
98                 check_definition(iface.instance_name, iface);
99
100         SetFlag set_anon(anonymous_block, iface.instance_name.empty());
101         TraversingVisitor::visit(iface);
102 }
103
104 void DeclarationValidator::visit(FunctionDeclaration &func)
105 {
106         if(Statement *previous = find_definition(func.name))
107                 if(!dynamic_cast<FunctionDeclaration *>(previous))
108                         multiple_definition(format("'%s'", func.name), func, *previous);
109
110         if(func.definition==&func)
111                 check_definition(func.name, func);
112         TraversingVisitor::visit(func);
113 }
114
115 } // namespace SL
116 } // namespace GL
117 } // namespace Msp