1 | // Copyright (C) 2021 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #include "glslsemantic_p.h" |
5 | #include "glslengine_p.h" |
6 | #include "glslparser_p.h" |
7 | #include "glslsymbols_p.h" |
8 | #include "glsltypes_p.h" |
9 | #include <QDebug> |
10 | |
11 | QT_BEGIN_NAMESPACE |
12 | |
13 | using namespace GLSL; |
14 | |
15 | Semantic::Semantic() |
16 | : _engine(nullptr) |
17 | , _scope(nullptr) |
18 | , _type(nullptr) |
19 | { |
20 | } |
21 | |
22 | Semantic::~Semantic() |
23 | { |
24 | } |
25 | |
26 | Engine *Semantic::switchEngine(Engine *engine) |
27 | { |
28 | Engine *previousEngine = _engine; |
29 | _engine = engine; |
30 | return previousEngine; |
31 | } |
32 | |
33 | Scope *Semantic::switchScope(Scope *scope) |
34 | { |
35 | Scope *previousScope = _scope; |
36 | _scope = scope; |
37 | return previousScope; |
38 | } |
39 | |
40 | Semantic::ExprResult Semantic::expression(ExpressionAST *ast) |
41 | { |
42 | Semantic::ExprResult r(_engine->undefinedType()); |
43 | std::swap(a&: _expr, b&: r); |
44 | accept(ast); |
45 | std::swap(a&: _expr, b&: r); |
46 | return r; |
47 | } |
48 | |
49 | void Semantic::statement(StatementAST *ast) |
50 | { |
51 | accept(ast); |
52 | } |
53 | |
54 | const Type *Semantic::type(TypeAST *ast) |
55 | { |
56 | const Type *t = _engine->undefinedType(); |
57 | std::swap(a&: _type, b&: t); |
58 | accept(ast); |
59 | std::swap(a&: _type, b&: t); |
60 | return t; |
61 | } |
62 | |
63 | void Semantic::declaration(DeclarationAST *ast) |
64 | { |
65 | accept(ast); |
66 | } |
67 | |
68 | void Semantic::translationUnit(TranslationUnitAST *ast, Scope *globalScope, Engine *engine) |
69 | { |
70 | Engine *previousEngine = switchEngine(engine); |
71 | Scope *previousScope = switchScope(scope: globalScope); |
72 | if (ast) { |
73 | for (List<DeclarationAST *> *it = ast->declarations; it; it = it->next) { |
74 | DeclarationAST *decl = it->value; |
75 | declaration(ast: decl); |
76 | } |
77 | } |
78 | (void) switchScope(scope: previousScope); |
79 | (void) switchEngine(engine: previousEngine); |
80 | } |
81 | |
82 | Semantic::ExprResult Semantic::expression(ExpressionAST *ast, Scope *scope, Engine *engine) |
83 | { |
84 | ExprResult result(engine->undefinedType()); |
85 | if (ast && scope) { |
86 | Engine *previousEngine = switchEngine(engine); |
87 | Scope *previousScope = switchScope(scope); |
88 | result = expression(ast); |
89 | (void) switchScope(scope: previousScope); |
90 | (void) switchEngine(engine: previousEngine); |
91 | } |
92 | return result; |
93 | } |
94 | |
95 | Semantic::ExprResult Semantic::functionIdentifier(FunctionIdentifierAST *ast) |
96 | { |
97 | ExprResult result; |
98 | if (ast) { |
99 | if (ast->name) { |
100 | if (Symbol *s = _scope->lookup(name: *ast->name)) { |
101 | if (s->asOverloadSet() != nullptr || s->asFunction() != nullptr) |
102 | result.type = s->type(); |
103 | else |
104 | _engine->error(line: ast->lineno, message: QString::fromLatin1(ba: "`%1' cannot be used as a function" ).arg(a: *ast->name)); |
105 | } else { |
106 | _engine->error(line: ast->lineno, message: QString::fromLatin1(ba: "`%1' was not declared in this scope" ).arg(a: *ast->name)); |
107 | } |
108 | } else if (ast->type) { |
109 | const Type *ty = type(ast: ast->type); |
110 | result.type = ty; |
111 | } |
112 | } |
113 | |
114 | return result; |
115 | } |
116 | |
117 | Symbol *Semantic::field(StructTypeAST::Field *ast) |
118 | { |
119 | // ast->name |
120 | const Type *ty = type(ast: ast->type); |
121 | QString name; |
122 | if (ast->name) |
123 | name = *ast->name; |
124 | return _engine->newVariable(scope: _scope, name, type: ty); |
125 | } |
126 | |
127 | void Semantic::parameterDeclaration(ParameterDeclarationAST *ast, Function *fun) |
128 | { |
129 | const Type *ty = type(ast: ast->type); |
130 | QString name; |
131 | if (ast->name) |
132 | name = *ast->name; |
133 | Argument *arg = _engine->newArgument(function: fun, name, type: ty); |
134 | fun->addArgument(arg); |
135 | } |
136 | |
137 | bool Semantic::visit(TranslationUnitAST *ast) |
138 | { |
139 | Q_UNUSED(ast) |
140 | Q_ASSERT(!"unreachable" ); |
141 | return false; |
142 | } |
143 | |
144 | bool Semantic::visit(FunctionIdentifierAST *ast) |
145 | { |
146 | Q_UNUSED(ast) |
147 | Q_ASSERT(!"unreachable" ); |
148 | return false; |
149 | } |
150 | |
151 | bool Semantic::visit(StructTypeAST::Field *ast) |
152 | { |
153 | Q_UNUSED(ast) |
154 | Q_ASSERT(!"unreachable" ); |
155 | return false; |
156 | } |
157 | |
158 | |
159 | // expressions |
160 | bool Semantic::visit(IdentifierExpressionAST *ast) |
161 | { |
162 | if (ast->name) { |
163 | if (Symbol *s = _scope->lookup(name: *ast->name)) |
164 | _expr.type = s->type(); |
165 | else |
166 | _engine->error(line: ast->lineno, message: QString::fromLatin1(ba: "`%1' was not declared in this scope" ).arg(a: *ast->name)); |
167 | } |
168 | return false; |
169 | } |
170 | |
171 | bool Semantic::visit(LiteralExpressionAST *ast) |
172 | { |
173 | if (ast->value) { |
174 | _expr.isConstant = true; |
175 | |
176 | if (ast->value->at(i: 0) == QLatin1Char('t') && *ast->value == QLatin1String("true" )) |
177 | _expr.type = _engine->boolType(); |
178 | else if (ast->value->at(i: 0) == QLatin1Char('f') && *ast->value == QLatin1String("false" )) |
179 | _expr.type = _engine->boolType(); |
180 | else if (ast->value->endsWith(c: QLatin1Char('u')) || ast->value->endsWith(c: QLatin1Char('U'))) |
181 | _expr.type = _engine->uintType(); |
182 | else if (ast->value->endsWith(s: QLatin1String("lf" )) || ast->value->endsWith(s: QLatin1String("LF" ))) |
183 | _expr.type = _engine->doubleType(); |
184 | else if (ast->value->endsWith(c: QLatin1Char('f')) || ast->value->endsWith(c: QLatin1Char('F')) || ast->value->contains(c: QLatin1Char('.'))) |
185 | _expr.type = _engine->floatType(); |
186 | else |
187 | _expr.type = _engine->intType(); |
188 | } |
189 | return false; |
190 | } |
191 | |
192 | bool Semantic::visit(BinaryExpressionAST *ast) |
193 | { |
194 | ExprResult left = expression(ast: ast->left); |
195 | ExprResult right = expression(ast: ast->right); |
196 | _expr.isConstant = left.isConstant && right.isConstant; |
197 | switch (ast->kind) { |
198 | case AST::Kind_ArrayAccess: |
199 | if (left.type) { |
200 | if (const IndexType *idxType = left.type->asIndexType()) |
201 | _expr = idxType->indexElementType(); |
202 | else |
203 | _engine->error(line: ast->lineno, message: QString::fromLatin1(ba: "Invalid type `%1' for array subscript" ).arg(a: left.type->toString())); |
204 | } |
205 | break; |
206 | |
207 | case AST::Kind_Modulus: |
208 | case AST::Kind_Multiply: |
209 | case AST::Kind_Divide: |
210 | case AST::Kind_Plus: |
211 | case AST::Kind_Minus: |
212 | case AST::Kind_ShiftLeft: |
213 | case AST::Kind_ShiftRight: |
214 | _expr.type = left.type; // ### not exactly |
215 | break; |
216 | |
217 | case AST::Kind_LessThan: |
218 | case AST::Kind_GreaterThan: |
219 | case AST::Kind_LessEqual: |
220 | case AST::Kind_GreaterEqual: |
221 | case AST::Kind_Equal: |
222 | case AST::Kind_NotEqual: |
223 | case AST::Kind_BitwiseAnd: |
224 | case AST::Kind_BitwiseXor: |
225 | case AST::Kind_BitwiseOr: |
226 | case AST::Kind_LogicalAnd: |
227 | case AST::Kind_LogicalXor: |
228 | case AST::Kind_LogicalOr: |
229 | _expr.type = _engine->boolType(); |
230 | break; |
231 | |
232 | case AST::Kind_Comma: |
233 | _expr = right; |
234 | break; |
235 | } |
236 | |
237 | return false; |
238 | } |
239 | |
240 | bool Semantic::visit(UnaryExpressionAST *ast) |
241 | { |
242 | ExprResult expr = expression(ast: ast->expr); |
243 | _expr = expr; |
244 | return false; |
245 | } |
246 | |
247 | bool Semantic::visit(TernaryExpressionAST *ast) |
248 | { |
249 | ExprResult first = expression(ast: ast->first); |
250 | ExprResult second = expression(ast: ast->second); |
251 | ExprResult third = expression(ast: ast->third); |
252 | _expr.isConstant = first.isConstant && second.isConstant && third.isConstant; |
253 | _expr.type = second.type; |
254 | return false; |
255 | } |
256 | |
257 | bool Semantic::visit(AssignmentExpressionAST *ast) |
258 | { |
259 | ExprResult variable = expression(ast: ast->variable); |
260 | ExprResult value = expression(ast: ast->value); |
261 | return false; |
262 | } |
263 | |
264 | bool Semantic::visit(MemberAccessExpressionAST *ast) |
265 | { |
266 | ExprResult expr = expression(ast: ast->expr); |
267 | if (expr.type && ast->field) { |
268 | if (const VectorType *vecTy = expr.type->asVectorType()) { |
269 | if (Symbol *s = vecTy->find(name: *ast->field)) |
270 | _expr.type = s->type(); |
271 | else |
272 | _engine->error(line: ast->lineno, message: QString::fromLatin1(ba: "`%1' has no member named `%2'" ).arg(a: vecTy->name()).arg(a: *ast->field)); |
273 | } else if (const Struct *structTy = expr.type->asStructType()) { |
274 | if (Symbol *s = structTy->find(name: *ast->field)) |
275 | _expr.type = s->type(); |
276 | else |
277 | _engine->error(line: ast->lineno, message: QString::fromLatin1(ba: "`%1' has no member named `%2'" ).arg(a: structTy->name()).arg(a: *ast->field)); |
278 | } else { |
279 | _engine->error(line: ast->lineno, message: QString::fromLatin1(ba: "Requested for member `%1', in a non class or vec instance" ).arg(a: *ast->field)); |
280 | } |
281 | } |
282 | return false; |
283 | } |
284 | |
285 | bool Semantic::implicitCast(const Type *type, const Type *target) const |
286 | { |
287 | if (! (type && target)) { |
288 | return false; |
289 | } else if (type->isEqualTo(other: target)) { |
290 | return true; |
291 | } else if (target->asUIntType() != nullptr) { |
292 | return type->asIntType() != nullptr; |
293 | } else if (target->asFloatType() != nullptr) { |
294 | return type->asIntType() != nullptr || |
295 | type->asUIntType() != nullptr; |
296 | } else if (target->asDoubleType() != nullptr) { |
297 | return type->asIntType() != nullptr || |
298 | type->asUIntType() != nullptr || |
299 | type->asFloatType() != nullptr; |
300 | } else if (const VectorType *targetVecTy = target->asVectorType()) { |
301 | if (const VectorType *vecTy = type->asVectorType()) { |
302 | if (targetVecTy->dimension() == vecTy->dimension()) { |
303 | const Type *targetElementType = targetVecTy->elementType(); |
304 | const Type *elementType = vecTy->elementType(); |
305 | |
306 | if (targetElementType->asUIntType() != nullptr) { |
307 | // uvec* -> ivec* |
308 | return elementType->asIntType() != nullptr; |
309 | } else if (targetElementType->asFloatType() != nullptr) { |
310 | // vec* -> ivec* | uvec* |
311 | return elementType->asIntType() != nullptr || |
312 | elementType->asUIntType() != nullptr; |
313 | } else if (targetElementType->asDoubleType() != nullptr) { |
314 | // dvec* -> ivec* | uvec* | fvec* |
315 | return elementType->asIntType() != nullptr || |
316 | elementType->asUIntType() != nullptr || |
317 | elementType->asFloatType() != nullptr; |
318 | } |
319 | } |
320 | } |
321 | } else if (const MatrixType *targetMatTy = target->asMatrixType()) { |
322 | if (const MatrixType *matTy = type->asMatrixType()) { |
323 | if (targetMatTy->columns() == matTy->columns() && |
324 | targetMatTy->rows() == matTy->rows()) { |
325 | const Type *targetElementType = targetMatTy->elementType(); |
326 | const Type *elementType = matTy->elementType(); |
327 | |
328 | if (targetElementType->asDoubleType() != nullptr) { |
329 | // dmat* -> mat* |
330 | return elementType->asFloatType() != nullptr; |
331 | } |
332 | } |
333 | } |
334 | } |
335 | |
336 | return false; |
337 | } |
338 | |
339 | bool Semantic::visit(FunctionCallExpressionAST *ast) |
340 | { |
341 | ExprResult expr = expression(ast: ast->expr); |
342 | ExprResult id = functionIdentifier(ast: ast->id); |
343 | QVector<ExprResult> actuals; |
344 | for (List<ExpressionAST *> *it = ast->arguments; it; it = it->next) { |
345 | ExprResult arg = expression(ast: it->value); |
346 | actuals.append(t: arg); |
347 | } |
348 | if (id.isValid()) { |
349 | if (const Function *funTy = id.type->asFunctionType()) { |
350 | if (actuals.size() < funTy->argumentCount()) |
351 | _engine->error(line: ast->lineno, message: QString::fromLatin1(ba: "not enough arguments" )); |
352 | else if (actuals.size() > funTy->argumentCount()) |
353 | _engine->error(line: ast->lineno, message: QString::fromLatin1(ba: "too many arguments" )); |
354 | _expr.type = funTy->returnType(); |
355 | } else if (const OverloadSet *overloads = id.type->asOverloadSetType()) { |
356 | QVector<Function *> candidates; |
357 | foreach (Function *f, overloads->functions()) { |
358 | if (f->argumentCount() == actuals.size()) { |
359 | int argc = 0; |
360 | for (; argc < actuals.size(); ++argc) { |
361 | const Type *actualTy = actuals.at(i: argc).type; |
362 | const Type *argumentTy = f->argumentAt(index: argc)->type(); |
363 | if (! implicitCast(type: actualTy, target: argumentTy)) |
364 | break; |
365 | } |
366 | |
367 | if (argc == actuals.size()) |
368 | candidates.append(t: f); |
369 | } |
370 | } |
371 | |
372 | if (candidates.isEmpty()) { |
373 | // ### error, unresolved call. |
374 | Q_ASSERT(! overloads->functions().isEmpty()); |
375 | |
376 | _expr.type = overloads->functions().constFirst()->returnType(); |
377 | } else { |
378 | _expr.type = candidates.constFirst()->returnType(); |
379 | |
380 | if (candidates.size() != 1) { |
381 | // ### error, ambiguous call |
382 | } |
383 | } |
384 | } else { |
385 | // called as constructor, e.g. vec2(a, b) |
386 | _expr.type = id.type; |
387 | } |
388 | } |
389 | |
390 | return false; |
391 | } |
392 | |
393 | bool Semantic::visit(DeclarationExpressionAST *ast) |
394 | { |
395 | const Type *ty = type(ast: ast->type); |
396 | Q_UNUSED(ty) |
397 | // ast->name |
398 | ExprResult initializer = expression(ast: ast->initializer); |
399 | return false; |
400 | } |
401 | |
402 | |
403 | // statements |
404 | bool Semantic::visit(ExpressionStatementAST *ast) |
405 | { |
406 | ExprResult expr = expression(ast: ast->expr); |
407 | return false; |
408 | } |
409 | |
410 | bool Semantic::visit(CompoundStatementAST *ast) |
411 | { |
412 | Block *block = _engine->newBlock(scope: _scope); |
413 | Scope *previousScope = switchScope(scope: block); |
414 | ast->symbol = block; |
415 | for (List<StatementAST *> *it = ast->statements; it; it = it->next) { |
416 | StatementAST *stmt = it->value; |
417 | statement(ast: stmt); |
418 | } |
419 | (void) switchScope(scope: previousScope); |
420 | return false; |
421 | } |
422 | |
423 | bool Semantic::visit(IfStatementAST *ast) |
424 | { |
425 | ExprResult condition = expression(ast: ast->condition); |
426 | statement(ast: ast->thenClause); |
427 | statement(ast: ast->elseClause); |
428 | return false; |
429 | } |
430 | |
431 | bool Semantic::visit(WhileStatementAST *ast) |
432 | { |
433 | ExprResult condition = expression(ast: ast->condition); |
434 | statement(ast: ast->body); |
435 | return false; |
436 | } |
437 | |
438 | bool Semantic::visit(DoStatementAST *ast) |
439 | { |
440 | statement(ast: ast->body); |
441 | ExprResult condition = expression(ast: ast->condition); |
442 | return false; |
443 | } |
444 | |
445 | bool Semantic::visit(ForStatementAST *ast) |
446 | { |
447 | statement(ast: ast->init); |
448 | ExprResult condition = expression(ast: ast->condition); |
449 | ExprResult increment = expression(ast: ast->increment); |
450 | statement(ast: ast->body); |
451 | return false; |
452 | } |
453 | |
454 | bool Semantic::visit(JumpStatementAST *ast) |
455 | { |
456 | Q_UNUSED(ast) |
457 | return false; |
458 | } |
459 | |
460 | bool Semantic::visit(ReturnStatementAST *ast) |
461 | { |
462 | ExprResult expr = expression(ast: ast->expr); |
463 | return false; |
464 | } |
465 | |
466 | bool Semantic::visit(SwitchStatementAST *ast) |
467 | { |
468 | ExprResult expr = expression(ast: ast->expr); |
469 | statement(ast: ast->body); |
470 | return false; |
471 | } |
472 | |
473 | bool Semantic::visit(CaseLabelStatementAST *ast) |
474 | { |
475 | ExprResult expr = expression(ast: ast->expr); |
476 | return false; |
477 | } |
478 | |
479 | bool Semantic::visit(DeclarationStatementAST *ast) |
480 | { |
481 | declaration(ast: ast->decl); |
482 | return false; |
483 | } |
484 | |
485 | |
486 | // types |
487 | bool Semantic::visit(BasicTypeAST *ast) |
488 | { |
489 | switch (ast->token) { |
490 | case Parser::T_VOID: |
491 | _type = _engine->voidType(); |
492 | break; |
493 | |
494 | case Parser::T_BOOL: |
495 | _type = _engine->boolType(); |
496 | break; |
497 | |
498 | case Parser::T_INT: |
499 | _type = _engine->intType(); |
500 | break; |
501 | |
502 | case Parser::T_UINT: |
503 | _type = _engine->uintType(); |
504 | break; |
505 | |
506 | case Parser::T_FLOAT: |
507 | _type = _engine->floatType(); |
508 | break; |
509 | |
510 | case Parser::T_DOUBLE: |
511 | _type = _engine->doubleType(); |
512 | break; |
513 | |
514 | // bvec |
515 | case Parser::T_BVEC2: |
516 | _type = _engine->vectorType(elementType: _engine->boolType(), dimension: 2); |
517 | break; |
518 | |
519 | case Parser::T_BVEC3: |
520 | _type = _engine->vectorType(elementType: _engine->boolType(), dimension: 3); |
521 | break; |
522 | |
523 | case Parser::T_BVEC4: |
524 | _type = _engine->vectorType(elementType: _engine->boolType(), dimension: 4); |
525 | break; |
526 | |
527 | // ivec |
528 | case Parser::T_IVEC2: |
529 | _type = _engine->vectorType(elementType: _engine->intType(), dimension: 2); |
530 | break; |
531 | |
532 | case Parser::T_IVEC3: |
533 | _type = _engine->vectorType(elementType: _engine->intType(), dimension: 3); |
534 | break; |
535 | |
536 | case Parser::T_IVEC4: |
537 | _type = _engine->vectorType(elementType: _engine->intType(), dimension: 4); |
538 | break; |
539 | |
540 | // uvec |
541 | case Parser::T_UVEC2: |
542 | _type = _engine->vectorType(elementType: _engine->uintType(), dimension: 2); |
543 | break; |
544 | |
545 | case Parser::T_UVEC3: |
546 | _type = _engine->vectorType(elementType: _engine->uintType(), dimension: 3); |
547 | break; |
548 | |
549 | case Parser::T_UVEC4: |
550 | _type = _engine->vectorType(elementType: _engine->uintType(), dimension: 4); |
551 | break; |
552 | |
553 | // vec |
554 | case Parser::T_VEC2: |
555 | _type = _engine->vectorType(elementType: _engine->floatType(), dimension: 2); |
556 | break; |
557 | |
558 | case Parser::T_VEC3: |
559 | _type = _engine->vectorType(elementType: _engine->floatType(), dimension: 3); |
560 | break; |
561 | |
562 | case Parser::T_VEC4: |
563 | _type = _engine->vectorType(elementType: _engine->floatType(), dimension: 4); |
564 | break; |
565 | |
566 | // dvec |
567 | case Parser::T_DVEC2: |
568 | _type = _engine->vectorType(elementType: _engine->doubleType(), dimension: 2); |
569 | break; |
570 | |
571 | case Parser::T_DVEC3: |
572 | _type = _engine->vectorType(elementType: _engine->doubleType(), dimension: 3); |
573 | break; |
574 | |
575 | case Parser::T_DVEC4: |
576 | _type = _engine->vectorType(elementType: _engine->doubleType(), dimension: 4); |
577 | break; |
578 | |
579 | // mat2 |
580 | case Parser::T_MAT2: |
581 | case Parser::T_MAT2X2: |
582 | _type = _engine->matrixType(elementType: _engine->floatType(), columns: 2, rows: 2); |
583 | break; |
584 | |
585 | case Parser::T_MAT2X3: |
586 | _type = _engine->matrixType(elementType: _engine->floatType(), columns: 2, rows: 3); |
587 | break; |
588 | |
589 | case Parser::T_MAT2X4: |
590 | _type = _engine->matrixType(elementType: _engine->floatType(), columns: 2, rows: 4); |
591 | break; |
592 | |
593 | // mat3 |
594 | case Parser::T_MAT3X2: |
595 | _type = _engine->matrixType(elementType: _engine->floatType(), columns: 3, rows: 2); |
596 | break; |
597 | |
598 | case Parser::T_MAT3: |
599 | case Parser::T_MAT3X3: |
600 | _type = _engine->matrixType(elementType: _engine->floatType(), columns: 3, rows: 3); |
601 | break; |
602 | |
603 | case Parser::T_MAT3X4: |
604 | _type = _engine->matrixType(elementType: _engine->floatType(), columns: 3, rows: 4); |
605 | break; |
606 | |
607 | // mat4 |
608 | case Parser::T_MAT4X2: |
609 | _type = _engine->matrixType(elementType: _engine->floatType(), columns: 4, rows: 2); |
610 | break; |
611 | |
612 | case Parser::T_MAT4X3: |
613 | _type = _engine->matrixType(elementType: _engine->floatType(), columns: 4, rows: 3); |
614 | break; |
615 | |
616 | case Parser::T_MAT4: |
617 | case Parser::T_MAT4X4: |
618 | _type = _engine->matrixType(elementType: _engine->floatType(), columns: 4, rows: 4); |
619 | break; |
620 | |
621 | |
622 | // dmat2 |
623 | case Parser::T_DMAT2: |
624 | case Parser::T_DMAT2X2: |
625 | _type = _engine->matrixType(elementType: _engine->doubleType(), columns: 2, rows: 2); |
626 | break; |
627 | |
628 | case Parser::T_DMAT2X3: |
629 | _type = _engine->matrixType(elementType: _engine->doubleType(), columns: 2, rows: 3); |
630 | break; |
631 | |
632 | case Parser::T_DMAT2X4: |
633 | _type = _engine->matrixType(elementType: _engine->doubleType(), columns: 2, rows: 4); |
634 | break; |
635 | |
636 | // dmat3 |
637 | case Parser::T_DMAT3X2: |
638 | _type = _engine->matrixType(elementType: _engine->doubleType(), columns: 3, rows: 2); |
639 | break; |
640 | |
641 | case Parser::T_DMAT3: |
642 | case Parser::T_DMAT3X3: |
643 | _type = _engine->matrixType(elementType: _engine->doubleType(), columns: 3, rows: 3); |
644 | break; |
645 | |
646 | case Parser::T_DMAT3X4: |
647 | _type = _engine->matrixType(elementType: _engine->doubleType(), columns: 3, rows: 4); |
648 | break; |
649 | |
650 | // dmat4 |
651 | case Parser::T_DMAT4X2: |
652 | _type = _engine->matrixType(elementType: _engine->doubleType(), columns: 4, rows: 2); |
653 | break; |
654 | |
655 | case Parser::T_DMAT4X3: |
656 | _type = _engine->matrixType(elementType: _engine->doubleType(), columns: 4, rows: 3); |
657 | break; |
658 | |
659 | case Parser::T_DMAT4: |
660 | case Parser::T_DMAT4X4: |
661 | _type = _engine->matrixType(elementType: _engine->doubleType(), columns: 4, rows: 4); |
662 | break; |
663 | |
664 | // samplers |
665 | case Parser::T_SAMPLER1D: |
666 | case Parser::T_SAMPLER2D: |
667 | case Parser::T_SAMPLER3D: |
668 | case Parser::T_SAMPLERCUBE: |
669 | case Parser::T_SAMPLER1DSHADOW: |
670 | case Parser::T_SAMPLER2DSHADOW: |
671 | case Parser::T_SAMPLERCUBESHADOW: |
672 | case Parser::T_SAMPLER1DARRAY: |
673 | case Parser::T_SAMPLER2DARRAY: |
674 | case Parser::T_SAMPLER1DARRAYSHADOW: |
675 | case Parser::T_SAMPLER2DARRAYSHADOW: |
676 | case Parser::T_SAMPLERCUBEARRAY: |
677 | case Parser::T_SAMPLERCUBEARRAYSHADOW: |
678 | case Parser::T_SAMPLER2DRECT: |
679 | case Parser::T_SAMPLER2DRECTSHADOW: |
680 | case Parser::T_SAMPLERBUFFER: |
681 | case Parser::T_SAMPLER2DMS: |
682 | case Parser::T_SAMPLER2DMSARRAY: |
683 | case Parser::T_ISAMPLER1D: |
684 | case Parser::T_ISAMPLER2D: |
685 | case Parser::T_ISAMPLER3D: |
686 | case Parser::T_ISAMPLERCUBE: |
687 | case Parser::T_ISAMPLER1DARRAY: |
688 | case Parser::T_ISAMPLER2DARRAY: |
689 | case Parser::T_ISAMPLERCUBEARRAY: |
690 | case Parser::T_ISAMPLER2DRECT: |
691 | case Parser::T_ISAMPLERBUFFER: |
692 | case Parser::T_ISAMPLER2DMS: |
693 | case Parser::T_ISAMPLER2DMSARRAY: |
694 | case Parser::T_USAMPLER1D: |
695 | case Parser::T_USAMPLER2D: |
696 | case Parser::T_USAMPLER3D: |
697 | case Parser::T_USAMPLERCUBE: |
698 | case Parser::T_USAMPLER1DARRAY: |
699 | case Parser::T_USAMPLER2DARRAY: |
700 | case Parser::T_USAMPLERCUBEARRAY: |
701 | case Parser::T_USAMPLER2DRECT: |
702 | case Parser::T_USAMPLERBUFFER: |
703 | case Parser::T_USAMPLER2DMS: |
704 | case Parser::T_USAMPLER2DMSARRAY: |
705 | _type = _engine->samplerType(kind: ast->token); |
706 | break; |
707 | |
708 | default: |
709 | _engine->error(line: ast->lineno, message: QString::fromLatin1(ba: "Unknown type `%1'" ).arg(a: QLatin1String(GLSLParserTable::spell[ast->token]))); |
710 | } |
711 | |
712 | return false; |
713 | } |
714 | |
715 | bool Semantic::visit(NamedTypeAST *ast) |
716 | { |
717 | if (ast->name) { |
718 | if (Symbol *s = _scope->lookup(name: *ast->name)) { |
719 | if (Struct *ty = s->asStruct()) { |
720 | _type = ty; |
721 | return false; |
722 | } |
723 | } |
724 | _engine->error(line: ast->lineno, message: QString::fromLatin1(ba: "Undefined type `%1'" ).arg(a: *ast->name)); |
725 | } |
726 | |
727 | return false; |
728 | } |
729 | |
730 | bool Semantic::visit(ArrayTypeAST *ast) |
731 | { |
732 | const Type *elementType = type(ast: ast->elementType); |
733 | Q_UNUSED(elementType) |
734 | ExprResult size = expression(ast: ast->size); |
735 | _type = _engine->arrayType(elementType); // ### ignore the size for now |
736 | return false; |
737 | } |
738 | |
739 | bool Semantic::visit(StructTypeAST *ast) |
740 | { |
741 | Struct *s = _engine->newStruct(scope: _scope); |
742 | if (ast->name) |
743 | s->setName(*ast->name); |
744 | if (Scope *e = s->scope()) |
745 | e->add(symbol: s); |
746 | Scope *previousScope = switchScope(scope: s); |
747 | for (List<StructTypeAST::Field *> *it = ast->fields; it; it = it->next) { |
748 | StructTypeAST::Field *f = it->value; |
749 | if (Symbol *member = field(ast: f)) |
750 | s->add(member); |
751 | } |
752 | (void) switchScope(scope: previousScope); |
753 | return false; |
754 | } |
755 | |
756 | bool Semantic::visit(QualifiedTypeAST *ast) |
757 | { |
758 | _type = type(ast: ast->type); |
759 | for (List<LayoutQualifierAST *> *it = ast->layout_list; it; it = it->next) { |
760 | LayoutQualifierAST *q = it->value; |
761 | // q->name; |
762 | // q->number; |
763 | Q_UNUSED(q) |
764 | } |
765 | return false; |
766 | } |
767 | |
768 | |
769 | // declarations |
770 | bool Semantic::visit(PrecisionDeclarationAST *ast) |
771 | { |
772 | const Type *ty = type(ast: ast->type); |
773 | Q_UNUSED(ty) |
774 | return false; |
775 | } |
776 | |
777 | bool Semantic::visit(ParameterDeclarationAST *ast) |
778 | { |
779 | Q_UNUSED(ast) |
780 | Q_ASSERT(!"unreachable" ); |
781 | return false; |
782 | } |
783 | |
784 | bool Semantic::visit(VariableDeclarationAST *ast) |
785 | { |
786 | if (!ast->type) |
787 | return false; |
788 | |
789 | const Type *ty = type(ast: ast->type); |
790 | ExprResult initializer = expression(ast: ast->initializer); |
791 | if (ast->name) { |
792 | QualifiedTypeAST *qtype = ast->type->asQualifiedType(); |
793 | int qualifiers = 0; |
794 | if (qtype) |
795 | qualifiers = qtype->qualifiers; |
796 | Variable *var = _engine->newVariable(scope: _scope, name: *ast->name, type: ty, qualifiers); |
797 | _scope->add(symbol: var); |
798 | } |
799 | return false; |
800 | } |
801 | |
802 | bool Semantic::visit(TypeDeclarationAST *ast) |
803 | { |
804 | const Type *ty = type(ast: ast->type); |
805 | Q_UNUSED(ty) |
806 | return false; |
807 | } |
808 | |
809 | bool Semantic::visit(TypeAndVariableDeclarationAST *ast) |
810 | { |
811 | declaration(ast: ast->typeDecl); |
812 | declaration(ast: ast->varDecl); |
813 | return false; |
814 | } |
815 | |
816 | bool Semantic::visit(InvariantDeclarationAST *ast) |
817 | { |
818 | Q_UNUSED(ast) |
819 | return false; |
820 | } |
821 | |
822 | bool Semantic::visit(InitDeclarationAST *ast) |
823 | { |
824 | for (List<DeclarationAST *> *it = ast->decls; it; it = it->next) { |
825 | DeclarationAST *decl = it->value; |
826 | declaration(ast: decl); |
827 | } |
828 | return false; |
829 | } |
830 | |
831 | bool Semantic::visit(FunctionDeclarationAST *ast) |
832 | { |
833 | Function *fun = _engine->newFunction(scope: _scope); |
834 | if (ast->name) |
835 | fun->setName(*ast->name); |
836 | |
837 | fun->setReturnType(type(ast: ast->returnType)); |
838 | |
839 | for (List<ParameterDeclarationAST *> *it = ast->params; it; it = it->next) { |
840 | ParameterDeclarationAST *decl = it->value; |
841 | parameterDeclaration(ast: decl, fun); |
842 | } |
843 | |
844 | if (Scope *enclosingScope = fun->scope()) |
845 | enclosingScope->add(symbol: fun); |
846 | |
847 | Scope *previousScope = switchScope(scope: fun); |
848 | statement(ast: ast->body); |
849 | (void) switchScope(scope: previousScope); |
850 | return false; |
851 | } |
852 | |
853 | QT_END_NAMESPACE |
854 | |