From dcd95f8d501677ed1a5054cd5da80964a8794d9e Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Thu, 2 Dec 2010 16:30:19 +0100
Subject: [PATCH] Handle array types and some initial work on implicit
 conversions.

---
 src/libs/glsl/glsl.h           |  2 +-
 src/libs/glsl/glslengine.cpp   |  6 +++
 src/libs/glsl/glslengine.h     |  2 +
 src/libs/glsl/glslsemantic.cpp | 82 ++++++++++++++++++++++++++++++----
 src/libs/glsl/glslsemantic.h   | 12 ++++-
 src/libs/glsl/glsltype.h       |  2 +-
 src/libs/glsl/glsltypes.h      | 14 +++---
 7 files changed, 101 insertions(+), 19 deletions(-)

diff --git a/src/libs/glsl/glsl.h b/src/libs/glsl/glsl.h
index e63ab44e895..25a39675900 100644
--- a/src/libs/glsl/glsl.h
+++ b/src/libs/glsl/glsl.h
@@ -52,12 +52,12 @@ class MemoryPool;
 class Type;
 class UndefinedType;
 class VoidType;
+class ScalarType;
 class BoolType;
 class IntType;
 class UIntType;
 class FloatType;
 class DoubleType;
-class OpaqueType;
 class IndexType;
 class VectorType;
 class MatrixType;
diff --git a/src/libs/glsl/glslengine.cpp b/src/libs/glsl/glslengine.cpp
index 2b6ec6e0391..bd30f7a0dce 100644
--- a/src/libs/glsl/glslengine.cpp
+++ b/src/libs/glsl/glslengine.cpp
@@ -185,6 +185,12 @@ const MatrixType *Engine::matrixType(const Type *elementType, int columns, int r
                                           vectorType(elementType, rows)));
 }
 
+const ArrayType *Engine::arrayType(const Type *elementType)
+{
+    return _arrayTypes.intern(ArrayType(elementType));
+}
+
+
 QList<DiagnosticMessage> Engine::diagnosticMessages() const
 {
     return _diagnosticMessages;
diff --git a/src/libs/glsl/glslengine.h b/src/libs/glsl/glslengine.h
index 2d668ba37f0..5e1c906509b 100644
--- a/src/libs/glsl/glslengine.h
+++ b/src/libs/glsl/glslengine.h
@@ -113,6 +113,7 @@ public:
     const SamplerType *samplerType(int kind);
     const VectorType *vectorType(const Type *elementType, int dimension);
     const MatrixType *matrixType(const Type *elementType, int columns, int rows);
+    const ArrayType *arrayType(const Type *elementType);
 
     // symbols
     Namespace *newNamespace();
@@ -136,6 +137,7 @@ private:
     QSet<QString> _numbers;
     TypeTable<VectorType> _vectorTypes;
     TypeTable<MatrixType> _matrixTypes;
+    TypeTable<ArrayType> _arrayTypes;
     TypeTable<SamplerType> _samplerTypes;
     MemoryPool _pool;
     QList<DiagnosticMessage> _diagnosticMessages;
diff --git a/src/libs/glsl/glslsemantic.cpp b/src/libs/glsl/glslsemantic.cpp
index 13542bb02cf..c01e460be2a 100644
--- a/src/libs/glsl/glslsemantic.cpp
+++ b/src/libs/glsl/glslsemantic.cpp
@@ -198,7 +198,11 @@ bool Semantic::visit(LiteralExpressionAST *ast)
     if (ast->value) {
         _expr.isConstant = true;
 
-        if (ast->value->endsWith(QLatin1Char('u')) || ast->value->endsWith(QLatin1Char('U')))
+        if (ast->value->at(0) == QLatin1Char('t') && *ast->value == QLatin1String("true"))
+            _expr.type = _engine->boolType();
+        else if (ast->value->at(0) == QLatin1Char('f') && *ast->value == QLatin1String("false"))
+            _expr.type = _engine->boolType();
+        else if (ast->value->endsWith(QLatin1Char('u')) || ast->value->endsWith(QLatin1Char('U')))
             _expr.type = _engine->uintType();
         else if (ast->value->endsWith(QLatin1String("lf")) || ast->value->endsWith(QLatin1String("LF")))
             _expr.type = _engine->doubleType();
@@ -217,11 +221,17 @@ bool Semantic::visit(BinaryExpressionAST *ast)
     _expr.isConstant = left.isConstant && right.isConstant;
     switch (ast->kind) {
     case AST::Kind_ArrayAccess:
+        if (left.type) {
+            if (const IndexType *idxType = left.type->asIndexType())
+                _expr = idxType->indexElementType();
+            else
+                _engine->error(ast->lineno, QString("Invalid type `%1' for array subscript").arg(left.type->toString()));
+        }
         break;
 
+    case AST::Kind_Modulus:
     case AST::Kind_Multiply:
     case AST::Kind_Divide:
-    case AST::Kind_Modulus:
     case AST::Kind_Plus:
     case AST::Kind_Minus:
     case AST::Kind_ShiftLeft:
@@ -301,8 +311,56 @@ bool Semantic::visit(MemberAccessExpressionAST *ast)
 
 bool Semantic::implicitCast(const Type *type, const Type *target) const
 {
-    // ### implement me
-    return type->isEqualTo(target);
+    if (! (type && target)) {
+        return false;
+    } else if (type->isEqualTo(target)) {
+        return true;
+    } else if (target->asUIntType() != 0) {
+        return type->asIntType() != 0;
+    } else if (target->asFloatType() != 0) {
+        return type->asIntType() != 0 ||
+                type->asUIntType() != 0;
+    } else if (target->asDoubleType() != 0) {
+        return type->asIntType() != 0 ||
+                type->asUIntType() != 0 ||
+                type->asFloatType() != 0;
+    } else if (const VectorType *targetVecTy = target->asVectorType()) {
+        if (const VectorType *vecTy = type->asVectorType()) {
+            if (targetVecTy->dimension() == vecTy->dimension()) {
+                const Type *targetElementType = targetVecTy->elementType();
+                const Type *elementType = vecTy->elementType();
+
+                if (targetElementType->asUIntType() != 0) {
+                    // uvec* -> ivec*
+                    return elementType->asIntType() != 0;
+                } else if (targetElementType->asFloatType() != 0) {
+                    // vec* -> ivec* | uvec*
+                    return elementType->asIntType() != 0 ||
+                            elementType->asUIntType() != 0;
+                } else if (targetElementType->asDoubleType() != 0) {
+                    // dvec* -> ivec* | uvec* | fvec*
+                    return elementType->asIntType() != 0 ||
+                            elementType->asUIntType() != 0 ||
+                            elementType->asFloatType() != 0;
+                }
+            }
+        }
+    } else if (const MatrixType *targetMatTy = target->asMatrixType()) {
+        if (const MatrixType *matTy = type->asMatrixType()) {
+            if (targetMatTy->columns() == matTy->columns() &&
+                    targetMatTy->rows() == matTy->rows()) {
+                const Type *targetElementType = targetMatTy->elementType();
+                const Type *elementType = matTy->elementType();
+
+                if (targetElementType->asDoubleType() != 0) {
+                    // dmat* -> mat*
+                    return elementType->asFloatType() != 0;
+                }
+            }
+        }
+    }
+
+    return false;
 }
 
 bool Semantic::visit(FunctionCallExpressionAST *ast)
@@ -337,11 +395,19 @@ bool Semantic::visit(FunctionCallExpressionAST *ast)
                         candidates.append(f);
                 }
             }
-            if (candidates.size() == 1)
-                _expr.type = candidates.first()->returnType();
-            else
+
+            if (candidates.isEmpty()) {
+                // ### error, unresolved call.
+                Q_ASSERT(! overloads->functions().isEmpty());
+
                 _expr.type = overloads->functions().first()->returnType();
+            } else {
+                _expr.type = candidates.first()->returnType();
 
+                if (candidates.size() != 1) {
+                    // ### error, ambiguous call
+                }
+            }
         } else {
             // called as constructor, e.g. vec2(a, b)
             _expr.type = id.type;
@@ -693,7 +759,7 @@ bool Semantic::visit(ArrayTypeAST *ast)
     const Type *elementType = type(ast->elementType);
     Q_UNUSED(elementType);
     ExprResult size = expression(ast->size);
-    // ### array type
+    _type = _engine->arrayType(elementType); // ### ignore the size for now
     return false;
 }
 
diff --git a/src/libs/glsl/glslsemantic.h b/src/libs/glsl/glslsemantic.h
index d3b0ce32141..49bfe67739c 100644
--- a/src/libs/glsl/glslsemantic.h
+++ b/src/libs/glsl/glslsemantic.h
@@ -30,6 +30,7 @@
 #define GLSLSEMANTIC_H
 
 #include "glslastvisitor.h"
+#include "glsltype.h"
 
 namespace GLSL {
 
@@ -43,8 +44,15 @@ public:
         ExprResult(const Type *type = 0, bool isConstant = false)
             : type(type), isConstant(isConstant) {}
 
-        bool isValid() const { return type != 0; }
-        operator bool() const { return type != 0; }
+        bool isValid() const {
+            if (! type)
+                return false;
+            else if (type->asUndefinedType() != 0)
+                return false;
+            return true;
+        }
+
+        operator bool() const { return isValid(); }
 
         const Type *type;
         bool isConstant;
diff --git a/src/libs/glsl/glsltype.h b/src/libs/glsl/glsltype.h
index 18ea9416d46..cc9c8ff94e7 100644
--- a/src/libs/glsl/glsltype.h
+++ b/src/libs/glsl/glsltype.h
@@ -47,7 +47,7 @@ public:
     virtual const UIntType *asUIntType() const { return 0; }
     virtual const FloatType *asFloatType() const { return 0; }
     virtual const DoubleType *asDoubleType() const { return 0; }
-    virtual const OpaqueType *asOpaqueType() const { return 0; }
+    virtual const ScalarType *asScalarType() const { return 0; }
     virtual const IndexType *asIndexType() const { return 0; }
     virtual const VectorType *asVectorType() const { return 0; }
     virtual const MatrixType *asMatrixType() const { return 0; }
diff --git a/src/libs/glsl/glsltypes.h b/src/libs/glsl/glsltypes.h
index f96171e905f..1b81f20e6e3 100644
--- a/src/libs/glsl/glsltypes.h
+++ b/src/libs/glsl/glsltypes.h
@@ -38,10 +38,10 @@
 
 namespace GLSL {
 
-class GLSL_EXPORT OpaqueType: public Type
+class GLSL_EXPORT ScalarType: public Type
 {
 public:
-    virtual const OpaqueType *asOpaqueType() const { return this; }
+    virtual const ScalarType *asScalarType() const { return this; }
 };
 
 class GLSL_EXPORT UndefinedType: public Type
@@ -62,7 +62,7 @@ public:
     virtual bool isLessThan(const Type *other) const;
 };
 
-class GLSL_EXPORT BoolType: public Type
+class GLSL_EXPORT BoolType: public ScalarType
 {
 public:
     virtual QString toString() const { return QLatin1String("bool"); }
@@ -71,7 +71,7 @@ public:
     virtual bool isLessThan(const Type *other) const;
 };
 
-class GLSL_EXPORT IntType: public Type
+class GLSL_EXPORT IntType: public ScalarType
 {
 public:
     virtual QString toString() const { return QLatin1String("int"); }
@@ -80,7 +80,7 @@ public:
     virtual bool isLessThan(const Type *other) const;
 };
 
-class GLSL_EXPORT UIntType: public Type
+class GLSL_EXPORT UIntType: public ScalarType
 {
 public:
     virtual QString toString() const { return QLatin1String("uint"); }
@@ -89,7 +89,7 @@ public:
     virtual bool isLessThan(const Type *other) const;
 };
 
-class GLSL_EXPORT FloatType: public Type
+class GLSL_EXPORT FloatType: public ScalarType
 {
 public:
     virtual QString toString() const { return QLatin1String("float"); }
@@ -98,7 +98,7 @@ public:
     virtual bool isLessThan(const Type *other) const;
 };
 
-class GLSL_EXPORT DoubleType: public Type
+class GLSL_EXPORT DoubleType: public ScalarType
 {
 public:
     virtual QString toString() const { return QLatin1String("double"); }
-- 
GitLab