1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "glsltypes_p.h"
5#include "glslsymbols_p.h"
6#include "glslengine_p.h"
7#include "glslparser_p.h"
8
9QT_BEGIN_NAMESPACE
10
11using namespace GLSL;
12
13bool UndefinedType::isEqualTo(const Type *other) const
14{
15 if (other && other->asUndefinedType() != nullptr)
16 return true;
17 return false;
18}
19
20bool UndefinedType::isLessThan(const Type *other) const
21{
22 Q_UNUSED(other)
23 Q_ASSERT(other != nullptr);
24 Q_ASSERT(other->asUndefinedType() != nullptr);
25 return false;
26}
27
28bool VoidType::isEqualTo(const Type *other) const
29{
30 if (other && other->asVoidType() != nullptr)
31 return true;
32 return false;
33}
34
35bool VoidType::isLessThan(const Type *other) const
36{
37 Q_UNUSED(other)
38 Q_ASSERT(other != nullptr);
39 Q_ASSERT(other->asVoidType() != nullptr);
40 return false;
41}
42
43bool BoolType::isEqualTo(const Type *other) const
44{
45 if (other && other->asBoolType() != nullptr)
46 return true;
47 return false;
48}
49
50bool BoolType::isLessThan(const Type *other) const
51{
52 Q_UNUSED(other)
53 Q_ASSERT(other != nullptr);
54 Q_ASSERT(other->asBoolType() != nullptr);
55 return false;
56}
57
58bool IntType::isEqualTo(const Type *other) const
59{
60 if (other && other->asIntType() != nullptr)
61 return true;
62 return false;
63}
64
65bool IntType::isLessThan(const Type *other) const
66{
67 Q_UNUSED(other)
68 Q_ASSERT(other != nullptr);
69 Q_ASSERT(other->asIntType() != nullptr);
70 return false;
71}
72
73bool UIntType::isEqualTo(const Type *other) const
74{
75 if (other && other->asUIntType() != nullptr)
76 return true;
77 return false;
78}
79
80bool UIntType::isLessThan(const Type *other) const
81{
82 Q_UNUSED(other)
83 Q_ASSERT(other != nullptr);
84 Q_ASSERT(other->asUIntType() != nullptr);
85 return false;
86}
87
88bool FloatType::isEqualTo(const Type *other) const
89{
90 if (other && other->asFloatType() != nullptr)
91 return true;
92 return false;
93}
94
95bool FloatType::isLessThan(const Type *other) const
96{
97 Q_UNUSED(other)
98 Q_ASSERT(other != nullptr);
99 Q_ASSERT(other->asFloatType() != nullptr);
100 return false;
101}
102
103bool DoubleType::isEqualTo(const Type *other) const
104{
105 if (other && other->asDoubleType() != nullptr)
106 return true;
107 return false;
108}
109
110bool DoubleType::isLessThan(const Type *other) const
111{
112 Q_UNUSED(other)
113 Q_ASSERT(other != nullptr);
114 Q_ASSERT(other->asDoubleType() != nullptr);
115 return false;
116}
117
118QString VectorType::toString() const
119{
120 const char *prefix = "";
121 if (elementType()->asBoolType() != nullptr)
122 prefix = "b";
123 else if (elementType()->asIntType() != nullptr)
124 prefix = "i'";
125 else if (elementType()->asUIntType() != nullptr)
126 prefix = "u";
127 else if (elementType()->asDoubleType() != nullptr)
128 prefix = "d";
129 return QString::fromLatin1(ba: "%1vec%2").arg(a: QLatin1String(prefix)).arg(a: _dimension);
130}
131
132void VectorType::add(Symbol *symbol)
133{
134 _members.insert(key: symbol->name(), value: symbol);
135}
136
137Symbol *VectorType::find(const QString &name) const
138{
139 return _members.value(key: name);
140}
141
142void VectorType::populateMembers(Engine *engine)
143{
144 if (_members.isEmpty()) {
145 populateMembers(engine, components: "xyzw");
146 populateMembers(engine, components: "rgba");
147 populateMembers(engine, components: "stpq");
148 }
149}
150
151void VectorType::populateMembers(Engine *engine, const char *components)
152{
153 // Single component swizzles.
154 for (int x = 0; x < _dimension; ++x) {
155 const QString *name = engine->identifier(s: components + x, n: 1);
156 add(symbol: engine->newVariable(scope: this, name: *name, type: elementType()));
157 }
158
159 // Two component swizzles.
160 const Type *vec2Type;
161 if (_dimension == 2)
162 vec2Type = this;
163 else
164 vec2Type = engine->vectorType(elementType: elementType(), dimension: 2);
165 for (int x = 0; x < _dimension; ++x) {
166 for (int y = 0; y < _dimension; ++y) {
167 QString name;
168 name += QLatin1Char(components[x]);
169 name += QLatin1Char(components[y]);
170 add(symbol: engine->newVariable
171 (scope: this, name: *engine->identifier(s: name), type: vec2Type));
172 }
173 }
174
175 // Three component swizzles.
176 const Type *vec3Type;
177 if (_dimension == 3)
178 vec3Type = this;
179 else if (_dimension < 3)
180 return;
181 else
182 vec3Type = engine->vectorType(elementType: elementType(), dimension: 3);
183 for (int x = 0; x < _dimension; ++x) {
184 for (int y = 0; y < _dimension; ++y) {
185 for (int z = 0; z < _dimension; ++z) {
186 QString name;
187 name += QLatin1Char(components[x]);
188 name += QLatin1Char(components[y]);
189 name += QLatin1Char(components[z]);
190 add(symbol: engine->newVariable
191 (scope: this, name: *engine->identifier(s: name), type: vec3Type));
192 }
193 }
194 }
195
196 // Four component swizzles.
197 if (_dimension != 4)
198 return;
199 for (int x = 0; x < _dimension; ++x) {
200 for (int y = 0; y < _dimension; ++y) {
201 for (int z = 0; z < _dimension; ++z) {
202 for (int w = 0; w < _dimension; ++w) {
203 QString name;
204 name += QLatin1Char(components[x]);
205 name += QLatin1Char(components[y]);
206 name += QLatin1Char(components[z]);
207 name += QLatin1Char(components[w]);
208 add(symbol: engine->newVariable
209 (scope: this, name: *engine->identifier(s: name), type: this));
210 }
211 }
212 }
213 }
214}
215
216bool VectorType::isEqualTo(const Type *other) const
217{
218 if (other) {
219 if (const VectorType *v = other->asVectorType()) {
220 if (_dimension != v->dimension())
221 return false;
222 else if (elementType() != v->elementType())
223 return false;
224 return true;
225 }
226 }
227 return false;
228}
229
230bool VectorType::isLessThan(const Type *other) const
231{
232 Q_ASSERT(other != nullptr);
233 const VectorType *vec = other->asVectorType();
234 Q_ASSERT(vec != nullptr);
235 if (_dimension < vec->dimension())
236 return true;
237 else if (_dimension == vec->dimension() && elementType() < vec->elementType())
238 return true;
239 return false;
240}
241
242QString MatrixType::toString() const
243{
244 const char *prefix = "";
245 if (elementType()->asBoolType() != nullptr)
246 prefix = "b";
247 else if (elementType()->asIntType() != nullptr)
248 prefix = "i";
249 else if (elementType()->asUIntType() != nullptr)
250 prefix = "u";
251 else if (elementType()->asDoubleType() != nullptr)
252 prefix = "d";
253 return QString::fromLatin1(ba: "%1mat%2x%3").arg(a: QLatin1String(prefix)).arg(a: _columns).arg(a: _rows);
254}
255
256bool MatrixType::isEqualTo(const Type *other) const
257{
258 if (other) {
259 if (const MatrixType *v = other->asMatrixType()) {
260 if (_columns != v->columns())
261 return false;
262 else if (_rows != v->rows())
263 return false;
264 else if (_elementType != v->elementType())
265 return false;
266 return true;
267 }
268 }
269 return false;
270}
271
272bool MatrixType::isLessThan(const Type *other) const
273{
274 Q_ASSERT(other != nullptr);
275 const MatrixType *mat = other->asMatrixType();
276 Q_ASSERT(mat != nullptr);
277 if (_columns < mat->columns()) {
278 return true;
279 } else if (_columns == mat->columns()) {
280 if (_rows < mat->rows())
281 return true;
282 else if (_rows == mat->rows() && _elementType < mat->elementType())
283 return true;
284 }
285 return false;
286}
287
288QString ArrayType::toString() const
289{
290 return elementType()->toString() + QLatin1String("[]");
291}
292
293bool ArrayType::isEqualTo(const Type *other) const
294{
295 if (other) {
296 if (const ArrayType *array = other->asArrayType())
297 return elementType()->isEqualTo(other: array->elementType());
298 }
299 return false;
300}
301
302bool ArrayType::isLessThan(const Type *other) const
303{
304 Q_ASSERT(other != nullptr);
305 const ArrayType *array = other->asArrayType();
306 Q_ASSERT(array != nullptr);
307 return elementType() < array->elementType();
308}
309
310QList<Symbol *> Struct::members() const
311{
312 QList<Symbol *> m;
313 foreach (Symbol *s, _members) {
314 if (! s->name().isEmpty())
315 m.append(t: s);
316 }
317 return m;
318}
319
320void Struct::add(Symbol *member)
321{
322 _members.append(t: member);
323}
324
325Symbol *Struct::find(const QString &name) const
326{
327 foreach (Symbol *s, _members) {
328 if (s->name() == name)
329 return s;
330 }
331 return nullptr;
332}
333
334bool Struct::isEqualTo(const Type *other) const
335{
336 Q_UNUSED(other)
337 return false;
338}
339
340bool Struct::isLessThan(const Type *other) const
341{
342 Q_UNUSED(other)
343 return false;
344}
345
346
347QString Function::toString() const
348{
349 return prettyPrint();
350}
351
352QString Function::prettyPrint() const
353{
354 QString proto;
355 proto += _returnType->toString();
356 proto += QLatin1Char(' ');
357 proto += name();
358 proto += QLatin1Char('(');
359 for (int i = 0; i < _arguments.size(); ++i) {
360 if (i != 0)
361 proto += QLatin1String(", ");
362 Argument *arg = _arguments.at(i);
363 proto += arg->type()->toString();
364 proto += QLatin1Char(' ');
365 proto += arg->name();
366 }
367 proto += QLatin1Char(')');
368 return proto;
369}
370
371const Type *Function::returnType() const
372{
373 return _returnType;
374}
375
376void Function::setReturnType(const Type *returnType)
377{
378 _returnType = returnType;
379}
380
381QVector<Argument *> Function::arguments() const
382{
383 return _arguments;
384}
385
386void Function::addArgument(Argument *arg)
387{
388 _arguments.append(t: arg);
389}
390
391int Function::argumentCount() const
392{
393 return _arguments.size();
394}
395
396Argument *Function::argumentAt(int index) const
397{
398 return _arguments.at(i: index);
399}
400
401bool Function::isEqualTo(const Type *other) const
402{
403 Q_UNUSED(other)
404 return false;
405}
406
407bool Function::isLessThan(const Type *other) const
408{
409 Q_UNUSED(other)
410 return false;
411}
412
413QList<Symbol *> Function::members() const
414{
415 QList<Symbol *> m;
416 foreach (Argument *arg, _arguments) {
417 if (! arg->name().isEmpty())
418 m.append(t: arg);
419 }
420 return m;
421}
422
423Symbol *Function::find(const QString &name) const
424{
425 foreach (Argument *arg, _arguments) {
426 if (arg->name() == name)
427 return arg;
428 }
429 return nullptr;
430}
431
432QString SamplerType::toString() const
433{
434 return QLatin1String(Parser::spell[_kind]);
435}
436
437bool SamplerType::isEqualTo(const Type *other) const
438{
439 if (other) {
440 if (const SamplerType *samp = other->asSamplerType())
441 return _kind == samp->kind();
442 }
443 return false;
444}
445
446bool SamplerType::isLessThan(const Type *other) const
447{
448 Q_ASSERT(other != nullptr);
449 const SamplerType *samp = other->asSamplerType();
450 Q_ASSERT(samp != nullptr);
451 return _kind < samp->kind();
452}
453
454OverloadSet::OverloadSet(Scope *enclosingScope)
455 : Scope(enclosingScope)
456{
457}
458
459QVector<Function *> OverloadSet::functions() const
460{
461 return _functions;
462}
463
464void OverloadSet::addFunction(Function *function)
465{
466 _functions.append(t: function);
467}
468
469const Type *OverloadSet::type() const
470{
471 return this;
472}
473
474Symbol *OverloadSet::find(const QString &) const
475{
476 return nullptr;
477}
478
479void OverloadSet::add(Symbol *symbol)
480{
481 if (symbol) {
482 if (Function *fun = symbol->asFunction())
483 addFunction(function: fun);
484 }
485}
486
487bool OverloadSet::isEqualTo(const Type *other) const
488{
489 Q_UNUSED(other)
490 return false;
491}
492
493bool OverloadSet::isLessThan(const Type *other) const
494{
495 Q_UNUSED(other)
496 return false;
497}
498
499QT_END_NAMESPACE
500

source code of qtquick3d/src/glslparser/glsltypes.cpp