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 | const auto functions = overloads->functions(); |
358 | for (Function *f : functions) { |
359 | if (f->argumentCount() == actuals.size()) { |
360 | int argc = 0; |
361 | for (; argc < actuals.size(); ++argc) { |
362 | const Type *actualTy = actuals.at(i: argc).type; |
363 | const Type *argumentTy = f->argumentAt(index: argc)->type(); |
364 | if (! implicitCast(type: actualTy, target: argumentTy)) |
365 | break; |
366 | } |
367 | |
368 | if (argc == actuals.size()) |
369 | candidates.append(t: f); |
370 | } |
371 | } |
372 | |
373 | if (candidates.isEmpty()) { |
374 | // ### error, unresolved call. |
375 | Q_ASSERT(!functions.isEmpty()); |
376 | |
377 | _expr.type = functions.front()->returnType(); |
378 | } else { |
379 | _expr.type = candidates.constFirst()->returnType(); |
380 | |
381 | if (candidates.size() != 1) { |
382 | // ### error, ambiguous call |
383 | } |
384 | } |
385 | } else { |
386 | // called as constructor, e.g. vec2(a, b) |
387 | _expr.type = id.type; |
388 | } |
389 | } |
390 | |
391 | return false; |
392 | } |
393 | |
394 | bool Semantic::visit(DeclarationExpressionAST *ast) |
395 | { |
396 | const Type *ty = type(ast: ast->type); |
397 | Q_UNUSED(ty) |
398 | // ast->name |
399 | ExprResult initializer = expression(ast: ast->initializer); |
400 | return false; |
401 | } |
402 | |
403 | |
404 | // statements |
405 | bool Semantic::visit(ExpressionStatementAST *ast) |
406 | { |
407 | ExprResult expr = expression(ast: ast->expr); |
408 | return false; |
409 | } |
410 | |
411 | bool Semantic::visit(CompoundStatementAST *ast) |
412 | { |
413 | Block *block = _engine->newBlock(scope: _scope); |
414 | Scope *previousScope = switchScope(scope: block); |
415 | ast->symbol = block; |
416 | for (List<StatementAST *> *it = ast->statements; it; it = it->next) { |
417 | StatementAST *stmt = it->value; |
418 | statement(ast: stmt); |
419 | } |
420 | (void) switchScope(scope: previousScope); |
421 | return false; |
422 | } |
423 | |
424 | bool Semantic::visit(IfStatementAST *ast) |
425 | { |
426 | ExprResult condition = expression(ast: ast->condition); |
427 | statement(ast: ast->thenClause); |
428 | statement(ast: ast->elseClause); |
429 | return false; |
430 | } |
431 | |
432 | bool Semantic::visit(WhileStatementAST *ast) |
433 | { |
434 | ExprResult condition = expression(ast: ast->condition); |
435 | statement(ast: ast->body); |
436 | return false; |
437 | } |
438 | |
439 | bool Semantic::visit(DoStatementAST *ast) |
440 | { |
441 | statement(ast: ast->body); |
442 | ExprResult condition = expression(ast: ast->condition); |
443 | return false; |
444 | } |
445 | |
446 | bool Semantic::visit(ForStatementAST *ast) |
447 | { |
448 | statement(ast: ast->init); |
449 | ExprResult condition = expression(ast: ast->condition); |
450 | ExprResult increment = expression(ast: ast->increment); |
451 | statement(ast: ast->body); |
452 | return false; |
453 | } |
454 | |
455 | bool Semantic::visit(JumpStatementAST *ast) |
456 | { |
457 | Q_UNUSED(ast) |
458 | return false; |
459 | } |
460 | |
461 | bool Semantic::visit(ReturnStatementAST *ast) |
462 | { |
463 | ExprResult expr = expression(ast: ast->expr); |
464 | return false; |
465 | } |
466 | |
467 | bool Semantic::visit(SwitchStatementAST *ast) |
468 | { |
469 | ExprResult expr = expression(ast: ast->expr); |
470 | statement(ast: ast->body); |
471 | return false; |
472 | } |
473 | |
474 | bool Semantic::visit(CaseLabelStatementAST *ast) |
475 | { |
476 | ExprResult expr = expression(ast: ast->expr); |
477 | return false; |
478 | } |
479 | |
480 | bool Semantic::visit(DeclarationStatementAST *ast) |
481 | { |
482 | declaration(ast: ast->decl); |
483 | return false; |
484 | } |
485 | |
486 | |
487 | // types |
488 | bool Semantic::visit(BasicTypeAST *ast) |
489 | { |
490 | switch (ast->token) { |
491 | case Parser::T_VOID: |
492 | _type = _engine->voidType(); |
493 | break; |
494 | |
495 | case Parser::T_BOOL: |
496 | _type = _engine->boolType(); |
497 | break; |
498 | |
499 | case Parser::T_INT: |
500 | _type = _engine->intType(); |
501 | break; |
502 | |
503 | case Parser::T_UINT: |
504 | _type = _engine->uintType(); |
505 | break; |
506 | |
507 | case Parser::T_FLOAT: |
508 | _type = _engine->floatType(); |
509 | break; |
510 | |
511 | case Parser::T_DOUBLE: |
512 | _type = _engine->doubleType(); |
513 | break; |
514 | |
515 | // bvec |
516 | case Parser::T_BVEC2: |
517 | _type = _engine->vectorType(elementType: _engine->boolType(), dimension: 2); |
518 | break; |
519 | |
520 | case Parser::T_BVEC3: |
521 | _type = _engine->vectorType(elementType: _engine->boolType(), dimension: 3); |
522 | break; |
523 | |
524 | case Parser::T_BVEC4: |
525 | _type = _engine->vectorType(elementType: _engine->boolType(), dimension: 4); |
526 | break; |
527 | |
528 | // ivec |
529 | case Parser::T_IVEC2: |
530 | _type = _engine->vectorType(elementType: _engine->intType(), dimension: 2); |
531 | break; |
532 | |
533 | case Parser::T_IVEC3: |
534 | _type = _engine->vectorType(elementType: _engine->intType(), dimension: 3); |
535 | break; |
536 | |
537 | case Parser::T_IVEC4: |
538 | _type = _engine->vectorType(elementType: _engine->intType(), dimension: 4); |
539 | break; |
540 | |
541 | // uvec |
542 | case Parser::T_UVEC2: |
543 | _type = _engine->vectorType(elementType: _engine->uintType(), dimension: 2); |
544 | break; |
545 | |
546 | case Parser::T_UVEC3: |
547 | _type = _engine->vectorType(elementType: _engine->uintType(), dimension: 3); |
548 | break; |
549 | |
550 | case Parser::T_UVEC4: |
551 | _type = _engine->vectorType(elementType: _engine->uintType(), dimension: 4); |
552 | break; |
553 | |
554 | // vec |
555 | case Parser::T_VEC2: |
556 | _type = _engine->vectorType(elementType: _engine->floatType(), dimension: 2); |
557 | break; |
558 | |
559 | case Parser::T_VEC3: |
560 | _type = _engine->vectorType(elementType: _engine->floatType(), dimension: 3); |
561 | break; |
562 | |
563 | case Parser::T_VEC4: |
564 | _type = _engine->vectorType(elementType: _engine->floatType(), dimension: 4); |
565 | break; |
566 | |
567 | // dvec |
568 | case Parser::T_DVEC2: |
569 | _type = _engine->vectorType(elementType: _engine->doubleType(), dimension: 2); |
570 | break; |
571 | |
572 | case Parser::T_DVEC3: |
573 | _type = _engine->vectorType(elementType: _engine->doubleType(), dimension: 3); |
574 | break; |
575 | |
576 | case Parser::T_DVEC4: |
577 | _type = _engine->vectorType(elementType: _engine->doubleType(), dimension: 4); |
578 | break; |
579 | |
580 | // mat2 |
581 | case Parser::T_MAT2: |
582 | case Parser::T_MAT2X2: |
583 | _type = _engine->matrixType(elementType: _engine->floatType(), columns: 2, rows: 2); |
584 | break; |
585 | |
586 | case Parser::T_MAT2X3: |
587 | _type = _engine->matrixType(elementType: _engine->floatType(), columns: 2, rows: 3); |
588 | break; |
589 | |
590 | case Parser::T_MAT2X4: |
591 | _type = _engine->matrixType(elementType: _engine->floatType(), columns: 2, rows: 4); |
592 | break; |
593 | |
594 | // mat3 |
595 | case Parser::T_MAT3X2: |
596 | _type = _engine->matrixType(elementType: _engine->floatType(), columns: 3, rows: 2); |
597 | break; |
598 | |
599 | case Parser::T_MAT3: |
600 | case Parser::T_MAT3X3: |
601 | _type = _engine->matrixType(elementType: _engine->floatType(), columns: 3, rows: 3); |
602 | break; |
603 | |
604 | case Parser::T_MAT3X4: |
605 | _type = _engine->matrixType(elementType: _engine->floatType(), columns: 3, rows: 4); |
606 | break; |
607 | |
608 | // mat4 |
609 | case Parser::T_MAT4X2: |
610 | _type = _engine->matrixType(elementType: _engine->floatType(), columns: 4, rows: 2); |
611 | break; |
612 | |
613 | case Parser::T_MAT4X3: |
614 | _type = _engine->matrixType(elementType: _engine->floatType(), columns: 4, rows: 3); |
615 | break; |
616 | |
617 | case Parser::T_MAT4: |
618 | case Parser::T_MAT4X4: |
619 | _type = _engine->matrixType(elementType: _engine->floatType(), columns: 4, rows: 4); |
620 | break; |
621 | |
622 | |
623 | // dmat2 |
624 | case Parser::T_DMAT2: |
625 | case Parser::T_DMAT2X2: |
626 | _type = _engine->matrixType(elementType: _engine->doubleType(), columns: 2, rows: 2); |
627 | break; |
628 | |
629 | case Parser::T_DMAT2X3: |
630 | _type = _engine->matrixType(elementType: _engine->doubleType(), columns: 2, rows: 3); |
631 | break; |
632 | |
633 | case Parser::T_DMAT2X4: |
634 | _type = _engine->matrixType(elementType: _engine->doubleType(), columns: 2, rows: 4); |
635 | break; |
636 | |
637 | // dmat3 |
638 | case Parser::T_DMAT3X2: |
639 | _type = _engine->matrixType(elementType: _engine->doubleType(), columns: 3, rows: 2); |
640 | break; |
641 | |
642 | case Parser::T_DMAT3: |
643 | case Parser::T_DMAT3X3: |
644 | _type = _engine->matrixType(elementType: _engine->doubleType(), columns: 3, rows: 3); |
645 | break; |
646 | |
647 | case Parser::T_DMAT3X4: |
648 | _type = _engine->matrixType(elementType: _engine->doubleType(), columns: 3, rows: 4); |
649 | break; |
650 | |
651 | // dmat4 |
652 | case Parser::T_DMAT4X2: |
653 | _type = _engine->matrixType(elementType: _engine->doubleType(), columns: 4, rows: 2); |
654 | break; |
655 | |
656 | case Parser::T_DMAT4X3: |
657 | _type = _engine->matrixType(elementType: _engine->doubleType(), columns: 4, rows: 3); |
658 | break; |
659 | |
660 | case Parser::T_DMAT4: |
661 | case Parser::T_DMAT4X4: |
662 | _type = _engine->matrixType(elementType: _engine->doubleType(), columns: 4, rows: 4); |
663 | break; |
664 | |
665 | // samplers |
666 | case Parser::T_SAMPLER1D: |
667 | case Parser::T_SAMPLER2D: |
668 | case Parser::T_SAMPLER3D: |
669 | case Parser::T_SAMPLERCUBE: |
670 | case Parser::T_SAMPLER1DSHADOW: |
671 | case Parser::T_SAMPLER2DSHADOW: |
672 | case Parser::T_SAMPLERCUBESHADOW: |
673 | case Parser::T_SAMPLER1DARRAY: |
674 | case Parser::T_SAMPLER2DARRAY: |
675 | case Parser::T_SAMPLER1DARRAYSHADOW: |
676 | case Parser::T_SAMPLER2DARRAYSHADOW: |
677 | case Parser::T_SAMPLERCUBEARRAY: |
678 | case Parser::T_SAMPLERCUBEARRAYSHADOW: |
679 | case Parser::T_SAMPLER2DRECT: |
680 | case Parser::T_SAMPLER2DRECTSHADOW: |
681 | case Parser::T_SAMPLERBUFFER: |
682 | case Parser::T_SAMPLER2DMS: |
683 | case Parser::T_SAMPLER2DMSARRAY: |
684 | case Parser::T_ISAMPLER1D: |
685 | case Parser::T_ISAMPLER2D: |
686 | case Parser::T_ISAMPLER3D: |
687 | case Parser::T_ISAMPLERCUBE: |
688 | case Parser::T_ISAMPLER1DARRAY: |
689 | case Parser::T_ISAMPLER2DARRAY: |
690 | case Parser::T_ISAMPLERCUBEARRAY: |
691 | case Parser::T_ISAMPLER2DRECT: |
692 | case Parser::T_ISAMPLERBUFFER: |
693 | case Parser::T_ISAMPLER2DMS: |
694 | case Parser::T_ISAMPLER2DMSARRAY: |
695 | case Parser::T_USAMPLER1D: |
696 | case Parser::T_USAMPLER2D: |
697 | case Parser::T_USAMPLER3D: |
698 | case Parser::T_USAMPLERCUBE: |
699 | case Parser::T_USAMPLER1DARRAY: |
700 | case Parser::T_USAMPLER2DARRAY: |
701 | case Parser::T_USAMPLERCUBEARRAY: |
702 | case Parser::T_USAMPLER2DRECT: |
703 | case Parser::T_USAMPLERBUFFER: |
704 | case Parser::T_USAMPLER2DMS: |
705 | case Parser::T_USAMPLER2DMSARRAY: |
706 | _type = _engine->samplerType(kind: ast->token); |
707 | break; |
708 | |
709 | default: |
710 | _engine->error(line: ast->lineno, message: QString::fromLatin1(ba: "Unknown type `%1'").arg(a: QLatin1String(GLSLParserTable::spell[ast->token]))); |
711 | } |
712 | |
713 | return false; |
714 | } |
715 | |
716 | bool Semantic::visit(NamedTypeAST *ast) |
717 | { |
718 | if (ast->name) { |
719 | if (Symbol *s = _scope->lookup(name: *ast->name)) { |
720 | if (Struct *ty = s->asStruct()) { |
721 | _type = ty; |
722 | return false; |
723 | } |
724 | } |
725 | _engine->error(line: ast->lineno, message: QString::fromLatin1(ba: "Undefined type `%1'").arg(a: *ast->name)); |
726 | } |
727 | |
728 | return false; |
729 | } |
730 | |
731 | bool Semantic::visit(ArrayTypeAST *ast) |
732 | { |
733 | const Type *elementType = type(ast: ast->elementType); |
734 | Q_UNUSED(elementType) |
735 | ExprResult size = expression(ast: ast->size); |
736 | _type = _engine->arrayType(elementType); // ### ignore the size for now |
737 | return false; |
738 | } |
739 | |
740 | bool Semantic::visit(StructTypeAST *ast) |
741 | { |
742 | Struct *s = _engine->newStruct(scope: _scope); |
743 | if (ast->name) |
744 | s->setName(*ast->name); |
745 | if (Scope *e = s->scope()) |
746 | e->add(symbol: s); |
747 | Scope *previousScope = switchScope(scope: s); |
748 | for (List<StructTypeAST::Field *> *it = ast->fields; it; it = it->next) { |
749 | StructTypeAST::Field *f = it->value; |
750 | if (Symbol *member = field(ast: f)) |
751 | s->add(member); |
752 | } |
753 | (void) switchScope(scope: previousScope); |
754 | return false; |
755 | } |
756 | |
757 | bool Semantic::visit(QualifiedTypeAST *ast) |
758 | { |
759 | _type = type(ast: ast->type); |
760 | for (List<LayoutQualifierAST *> *it = ast->layout_list; it; it = it->next) { |
761 | LayoutQualifierAST *q = it->value; |
762 | // q->name; |
763 | // q->number; |
764 | Q_UNUSED(q) |
765 | } |
766 | return false; |
767 | } |
768 | |
769 | |
770 | // declarations |
771 | bool Semantic::visit(PrecisionDeclarationAST *ast) |
772 | { |
773 | const Type *ty = type(ast: ast->type); |
774 | Q_UNUSED(ty) |
775 | return false; |
776 | } |
777 | |
778 | bool Semantic::visit(ParameterDeclarationAST *ast) |
779 | { |
780 | Q_UNUSED(ast) |
781 | Q_ASSERT(!"unreachable"); |
782 | return false; |
783 | } |
784 | |
785 | bool Semantic::visit(VariableDeclarationAST *ast) |
786 | { |
787 | if (!ast->type) |
788 | return false; |
789 | |
790 | const Type *ty = type(ast: ast->type); |
791 | ExprResult initializer = expression(ast: ast->initializer); |
792 | if (ast->name) { |
793 | QualifiedTypeAST *qtype = ast->type->asQualifiedType(); |
794 | int qualifiers = 0; |
795 | if (qtype) |
796 | qualifiers = qtype->qualifiers; |
797 | Variable *var = _engine->newVariable(scope: _scope, name: *ast->name, type: ty, qualifiers); |
798 | _scope->add(symbol: var); |
799 | } |
800 | return false; |
801 | } |
802 | |
803 | bool Semantic::visit(TypeDeclarationAST *ast) |
804 | { |
805 | const Type *ty = type(ast: ast->type); |
806 | Q_UNUSED(ty) |
807 | return false; |
808 | } |
809 | |
810 | bool Semantic::visit(TypeAndVariableDeclarationAST *ast) |
811 | { |
812 | declaration(ast: ast->typeDecl); |
813 | declaration(ast: ast->varDecl); |
814 | return false; |
815 | } |
816 | |
817 | bool Semantic::visit(InvariantDeclarationAST *ast) |
818 | { |
819 | Q_UNUSED(ast) |
820 | return false; |
821 | } |
822 | |
823 | bool Semantic::visit(InitDeclarationAST *ast) |
824 | { |
825 | for (List<DeclarationAST *> *it = ast->decls; it; it = it->next) { |
826 | DeclarationAST *decl = it->value; |
827 | declaration(ast: decl); |
828 | } |
829 | return false; |
830 | } |
831 | |
832 | bool Semantic::visit(FunctionDeclarationAST *ast) |
833 | { |
834 | Function *fun = _engine->newFunction(scope: _scope); |
835 | if (ast->name) |
836 | fun->setName(*ast->name); |
837 | |
838 | fun->setReturnType(type(ast: ast->returnType)); |
839 | |
840 | for (List<ParameterDeclarationAST *> *it = ast->params; it; it = it->next) { |
841 | ParameterDeclarationAST *decl = it->value; |
842 | parameterDeclaration(ast: decl, fun); |
843 | } |
844 | |
845 | if (Scope *enclosingScope = fun->scope()) |
846 | enclosingScope->add(symbol: fun); |
847 | |
848 | Scope *previousScope = switchScope(scope: fun); |
849 | statement(ast: ast->body); |
850 | (void) switchScope(scope: previousScope); |
851 | return false; |
852 | } |
853 | |
854 | QT_END_NAMESPACE |
855 |
Definitions
- Semantic
- ~Semantic
- switchEngine
- switchScope
- expression
- statement
- type
- declaration
- translationUnit
- expression
- functionIdentifier
- field
- parameterDeclaration
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- implicitCast
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
- visit
Start learning QML with our Intro Training
Find out more