Unify constant floats and constant doubles; they can all be constant doubles.
[platform/upstream/glslang.git] / glslang / MachineIndependent / parseConst.cpp
1 //
2 //Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
3 //All rights reserved.
4 //
5 //Redistribution and use in source and binary forms, with or without
6 //modification, are permitted provided that the following conditions
7 //are met:
8 //
9 //    Redistributions of source code must retain the above copyright
10 //    notice, this list of conditions and the following disclaimer.
11 //
12 //    Redistributions in binary form must reproduce the above
13 //    copyright notice, this list of conditions and the following
14 //    disclaimer in the documentation and/or other materials provided
15 //    with the distribution.
16 //
17 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
18 //    contributors may be used to endorse or promote products derived
19 //    from this software without specific prior written permission.
20 //
21 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 //POSSIBILITY OF SUCH DAMAGE.
33 //
34
35 #include "ParseHelper.h"
36
37 //
38 // Use this class to carry along data from node to node in 
39 // the traversal
40 //
41 class TConstTraverser : public TIntermTraverser {
42 public:
43     TConstTraverser(constUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, const TType& t) : unionArray(cUnion), type(t),
44         constructorType(constructType), singleConstantParam(singleConstParam), infoSink(sink), error(false), isMatrix(false), 
45         matrixCols(0), matrixRows(0) {  index = 0; tOp = EOpNull;}
46     int index ;
47     constUnion *unionArray;
48     TOperator tOp;
49     const TType& type;
50     TOperator constructorType;
51     bool singleConstantParam;
52     TInfoSink& infoSink;
53     bool error;
54     int size; // size of the constructor ( 4 for vec4)
55     bool isMatrix;
56     int matrixCols;
57     int matrixRows;
58 };
59
60 //
61 // The rest of the file are the traversal functions.  The last one
62 // is the one that starts the traversal.
63 //
64 // Return true from interior nodes to have the external traversal
65 // continue on to children.  If you process children yourself,
66 // return false.
67 //
68
69 void ParseSymbol(TIntermSymbol* node, TIntermTraverser* it)
70 {
71     TConstTraverser* oit = static_cast<TConstTraverser*>(it);
72     oit->infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
73
74     return;
75 }
76
77 bool ParseBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
78 {
79     TConstTraverser* oit = static_cast<TConstTraverser*>(it);
80     
81     TStorageQualifier qualifier = node->getType().getQualifier().storage;
82     
83     if (qualifier != EvqConst) {
84         const int maxSize = GlslangMaxTypeLength + 50;
85         char buf[maxSize];
86         snprintf(buf, maxSize, "'constructor' : assigning non-constant to %s", oit->type.getCompleteString().c_str());
87         oit->infoSink.info.message(EPrefixError, buf, node->getLine());
88         oit->error = true;
89
90         return false;  
91     }
92
93    oit->infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
94     
95     return false;
96 }
97
98 bool ParseUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it)
99 {
100     TConstTraverser* oit = static_cast<TConstTraverser*>(it);
101
102     const int maxSize = GlslangMaxTypeLength + 50;
103     char buf[maxSize];
104     snprintf(buf, maxSize, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
105     oit->infoSink.info.message(EPrefixError, buf, node->getLine());
106     oit->error = true;
107
108     return false;  
109 }
110
111 bool ParseAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it)
112 {
113     TConstTraverser* oit = static_cast<TConstTraverser*>(it);
114
115     if (!node->isConstructor() && node->getOp() != EOpComma) {
116         const int maxSize = GlslangMaxTypeLength + 50;
117         char buf[maxSize];
118         snprintf(buf, maxSize, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
119         oit->infoSink.info.message(EPrefixError, buf, node->getLine());
120         oit->error = true;
121
122         return false;  
123     }
124
125     if (node->getSequence().size() == 0) {
126         oit->error = true;
127
128         return false;
129     }
130
131     bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
132     if (flag) {
133         oit->singleConstantParam = true; 
134         oit->constructorType = node->getOp();
135         oit->size = node->getType().getObjectSize();
136
137         if (node->getType().isMatrix()) {
138             oit->isMatrix = true;
139             oit->matrixCols = node->getType().getMatrixCols();
140             oit->matrixRows = node->getType().getMatrixRows();
141         }
142     }       
143
144     for (TIntermSequence::iterator p = node->getSequence().begin(); 
145                                    p != node->getSequence().end(); p++) {
146
147         if (node->getOp() == EOpComma)
148             oit->index = 0;           
149
150         (*p)->traverse(oit);
151     }   
152     if (flag) 
153     {
154         oit->singleConstantParam = false;   
155         oit->constructorType = EOpNull;
156         oit->size = 0;
157         oit->isMatrix = false;
158         oit->matrixCols = 0;
159         oit->matrixRows = 0;
160     }
161
162     return false;
163 }
164
165 bool ParseSelection(bool /* preVisit */, TIntermSelection* node, TIntermTraverser* it)
166 {
167     TConstTraverser* oit = static_cast<TConstTraverser*>(it);
168     oit->infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
169     oit->error = true;
170     return false;
171 }
172
173 void ParseConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it)
174 {
175     TConstTraverser* oit = static_cast<TConstTraverser*>(it);
176     constUnion* leftUnionArray = oit->unionArray;
177     int instanceSize = oit->type.getObjectSize();
178
179     if (oit->index >= instanceSize)
180         return;
181
182     if (!oit->singleConstantParam) {
183         int size = node->getType().getObjectSize();
184     
185         constUnion *rightUnionArray = node->getUnionArrayPointer();
186         for (int i=0; i < size; i++) {
187             if (oit->index >= instanceSize)
188                 return;
189             leftUnionArray[oit->index] = rightUnionArray[i];
190
191             (oit->index)++;
192         }
193     } else {
194         int size, totalSize, matrixCols, matrixRows;
195         bool isMatrix = false;
196         size = oit->size;
197         matrixCols = oit->matrixCols;
198         matrixRows = oit->matrixRows;
199         isMatrix = oit->isMatrix;
200         totalSize = oit->index + size;
201         constUnion *rightUnionArray = node->getUnionArrayPointer();
202         if (!isMatrix) {
203             int count = 0;
204             for (int i = oit->index; i < totalSize; i++) {
205                 if (i >= instanceSize)
206                     return;
207
208                 leftUnionArray[i] = rightUnionArray[count];
209
210                 (oit->index)++;
211                 
212                 if (node->getType().getObjectSize() > 1)
213                     count++;
214             }
215         } else {  // for matrix constructors
216             int count = 0;
217             int index = oit->index;
218             for (int i = index; i < totalSize; i++) {
219                 if (i >= instanceSize)
220                     return;
221                 if (index - i == 0 || (i - index) % (matrixRows + 1) == 0 )
222                     leftUnionArray[i] = rightUnionArray[count];
223                 else 
224                     leftUnionArray[i].setDConst(0.0);
225
226                 (oit->index)++;
227
228                 if (node->getType().getObjectSize() > 1)
229                     count++;                
230             }
231         }
232     }
233 }
234
235 bool ParseLoop(bool /* preVisit */, TIntermLoop* node, TIntermTraverser* it)
236 {
237     TConstTraverser* oit = static_cast<TConstTraverser*>(it);
238     oit->infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
239     oit->error = true;
240     
241     return false;
242 }
243
244 bool ParseBranch(bool /* previsit*/, TIntermBranch* node, TIntermTraverser* it)
245 {
246     TConstTraverser* oit = static_cast<TConstTraverser*>(it);
247     oit->infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
248     oit->error = true;
249     
250     return false;
251 }
252
253 //
254 // This function is the one to call externally to start the traversal.
255 // Individual functions can be initialized to 0 to skip processing of that
256 // type of node.  It's children will still be processed.
257 //
258 bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, constUnion* unionArray, TOperator constructorType, const TType& t, bool singleConstantParam)
259 {
260     if (root == 0)
261         return false;
262
263     TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, t);
264     
265     it.visitAggregate = ParseAggregate;
266     it.visitBinary = ParseBinary;
267     it.visitConstantUnion = ParseConstantUnion;
268     it.visitSelection = ParseSelection;
269     it.visitSymbol = ParseSymbol;
270     it.visitUnary = ParseUnary;
271     it.visitLoop = ParseLoop;
272     it.visitBranch = ParseBranch;
273
274     root->traverse(&it);
275     if (it.error)
276         return true;
277     else
278         return false;
279 }