OSDN Git Service

Process binary expressions.
authorRoberto Raggi <roberto.raggi@nokia.com>
Tue, 30 Nov 2010 15:10:07 +0000 (16:10 +0100)
committerRoberto Raggi <roberto.raggi@nokia.com>
Tue, 30 Nov 2010 15:10:27 +0000 (16:10 +0100)
src/libs/glsl/glslsemantic.cpp
src/libs/glsl/glslsemantic.h

index cd3a10f..9e159a3 100644 (file)
@@ -219,6 +219,40 @@ bool Semantic::visit(BinaryExpressionAST *ast)
     ExprResult left = expression(ast->left);
     ExprResult right = expression(ast->right);
     _expr.isConstant = left.isConstant && right.isConstant;
+    switch (ast->kind) {
+    case AST::Kind_ArrayAccess:
+        break;
+
+    case AST::Kind_Multiply:
+    case AST::Kind_Divide:
+    case AST::Kind_Modulus:
+    case AST::Kind_Plus:
+    case AST::Kind_Minus:
+    case AST::Kind_ShiftLeft:
+    case AST::Kind_ShiftRight:
+        _expr.type = left.type; // ### not exactly
+        break;
+
+    case AST::Kind_LessThan:
+    case AST::Kind_GreaterThan:
+    case AST::Kind_LessEqual:
+    case AST::Kind_GreaterEqual:
+    case AST::Kind_Equal:
+    case AST::Kind_NotEqual:
+    case AST::Kind_BitwiseAnd:
+    case AST::Kind_BitwiseXor:
+    case AST::Kind_BitwiseOr:
+    case AST::Kind_LogicalAnd:
+    case AST::Kind_LogicalXor:
+    case AST::Kind_LogicalOr:
+        _expr.type = _engine->boolType();
+        break;
+
+    case AST::Kind_Comma:
+        _expr = right;
+        break;
+    }
+
     return false;
 }
 
@@ -235,6 +269,7 @@ bool Semantic::visit(TernaryExpressionAST *ast)
     ExprResult second = expression(ast->second);
     ExprResult third = expression(ast->third);
     _expr.isConstant = first.isConstant && second.isConstant && third.isConstant;
+    _expr.type = second.type;
     return false;
 }
 
@@ -252,24 +287,65 @@ bool Semantic::visit(MemberAccessExpressionAST *ast)
         if (const VectorType *vecTy = expr.type->asVectorType()) {
             if (Symbol *s = vecTy->find(*ast->field)) {
                 _expr.type = s->type();
+            } else {
+                _engine->error(ast->lineno, QString("`%1' has no member named `%2'").arg(vecTy->name()).arg(*ast->field));
             }
         } else if (const Struct *structTy = expr.type->asStructType()) {
             if (Symbol *s = structTy->find(*ast->field)) {
                 _expr.type = s->type();
+            } else {
+                _engine->error(ast->lineno, QString("`%1' has no member named `%2'").arg(structTy->name()).arg(*ast->field));
             }
         } else {
-            // error(ast->lineno, QString("Requested for member `%1', in a non class or vec instance").arg(*ast->field));
+            _engine->error(ast->lineno, QString("Requested for member `%1', in a non class or vec instance").arg(*ast->field));
         }
     }
     return false;
 }
 
+bool Semantic::implicitCast(const Type *type, const Type *target) const
+{
+    // ### implement me
+    return type->isEqualTo(target);
+}
+
 bool Semantic::visit(FunctionCallExpressionAST *ast)
 {
     ExprResult expr = expression(ast->expr);
     ExprResult id = functionIdentifier(ast->id);
+    QVector<ExprResult> actuals;
     for (List<ExpressionAST *> *it = ast->arguments; it; it = it->next) {
         ExprResult arg = expression(it->value);
+        actuals.append(arg);
+    }
+    if (id.isValid()) {
+        if (const Function *funTy = id.type->asFunctionType()) {
+            if (actuals.size() < funTy->argumentCount())
+                _engine->error(ast->lineno, QString("not enough arguments"));
+            else if (actuals.size() > funTy->argumentCount())
+                _engine->error(ast->lineno, QString("too many arguments"));
+            _expr.type = funTy->returnType();
+        } else if (const OverloadSet *overloads = id.type->asOverloadSetType()) {
+            QVector<GLSL::Function *> candidates;
+            foreach (GLSL::Function *f, overloads->functions()) {
+                if (f->argumentCount() == actuals.size()) {
+                    int argc = 0;
+                    for (; argc < actuals.size(); ++argc) {
+                        const Type *actualTy = actuals.at(argc).type;
+                        const Type *argumentTy = f->argumentAt(argc)->type();
+                        if (! implicitCast(actualTy, argumentTy))
+                            break;
+                    }
+
+                    if (argc == actuals.size())
+                        candidates.append(f);
+                }
+            }
+            if (candidates.size() == 1)
+                _expr.type = candidates.first()->returnType();
+            else
+                _expr.type = overloads->functions().first()->returnType();
+        }
     }
 
     return false;
index 992a6e8..d3b0ce3 100644 (file)
@@ -57,6 +57,8 @@ protected:
     Engine *switchEngine(Engine *engine);
     Scope *switchScope(Scope *scope);
 
+    bool implicitCast(const Type *type, const Type *target) const;
+
     ExprResult expression(ExpressionAST *ast);
     void statement(StatementAST *ast);
     const Type *type(TypeAST *ast);