Bläddra i källkod

get ready to handle "IS" in a special way

Vladislav Folts 11 år sedan
förälder
incheckning
476a8559ef
3 ändrade filer med 76 tillägg och 75 borttagningar
  1. 26 44
      src/context.js
  2. 6 6
      src/eberon/EberonOperator.ob
  3. 44 25
      src/ob/Operator.ob

+ 26 - 44
src/context.js

@@ -896,6 +896,7 @@ var RelationOps = Class.extend({
              : type == basicTypes.set   ? op.setInclR
                                         : undefined;
     },
+    is: function(){return op.is;},
     eqExpect: function(){return "numeric type or SET or BOOLEAN or CHAR or character array or POINTER or PROCEDURE";},
     strongRelExpect: function(){return "numeric type or CHAR or character array";},
     relExpect: function(){return "numeric type or SET or CHAR or character array";}
@@ -903,8 +904,18 @@ var RelationOps = Class.extend({
 
 var relationOps = new RelationOps();
 
-function relationOp(leftType, rightType, literal, ops){
-    var type = useTypeInRelation(leftType, rightType);
+function checkSetHasBit(leftType, rightType, context){
+    if (!Type.isInt(leftType))
+        throw new Errors.Error(
+            Type.intsDescription() + " expected as an element of SET, got '" + Type.typeName(leftType) + "'");
+    checkImplicitCast(context.language().types, rightType, basicTypes.set);
+}
+
+function relationOp(leftType, rightType, literal, ops, context){
+    var type = 
+          literal == "IS" ? unwrapType(rightType)
+        : literal == "IN" ? checkSetHasBit(leftType, rightType, context)
+                          : useTypeInRelation(leftType, rightType);
     var o;
     var mismatch;
     switch (literal){
@@ -938,6 +949,15 @@ function relationOp(leftType, rightType, literal, ops){
             if (!o)
                 mismatch = ops.relExpect();
             break;
+        case "IS":
+            o = function(leftExpression){
+                    var d = leftExpression.designator();
+                    checkTypeCast(d ? d.info() : undefined, leftType, type, "type test");
+                    return ops.is()(leftExpression, Code.makeExpression(castCode(type, context)));
+                };
+            break;
+        case "IN":
+            o = op.setHasBit;
         }
     if (mismatch)
         throwOperatorTypeMismatch(literal, mismatch, type);
@@ -1214,50 +1234,12 @@ exports.Expression = ChainedContext.extend({
         }
 
         var leftExpression = this.__expression;
-        var leftType = leftExpression.type();
-        var leftCode = leftExpression.code();
         var rightExpression = e;
-        var rightType = rightExpression.type();
-        var rightCode = rightExpression.code();
-        var resultExpression;
-        var code;
-
-        if (this.__relation == "IN"){
-            if (!Type.isInt(leftType))
-                throw new Errors.Error(
-                    Type.intsDescription() + " expected as an element of SET, got '" + Type.typeName(leftType) + "'");
-            checkImplicitCast(this.language().types, rightType, basicTypes.set);
-
-            code = "1 << " + leftCode + " & " + rightCode;
-        }
-        else if (this.__relation == "IS"){
-            rightType = unwrapType(rightType);
-            var d = leftExpression.designator();
-            checkTypeCast(d ? d.info() : undefined, leftType, rightType, "type test");
-            //rightExpression = , rightType);
-            resultExpression = op.is(leftExpression, Code.makeExpression(castCode(rightType, this)));
-            code = resultExpression.code();
-            //code = leftCode + " instanceof " + castCode(rightType, this);
-        }
-        else {
-            leftExpression = promoteTypeInExpression(leftExpression, rightType);
-            rightExpression = promoteTypeInExpression(rightExpression, leftType);
-            leftCode = leftExpression.code();
-            rightCode = rightExpression.code();
-            //checkImplicitCast(rightExpression.type(), leftExpression.type());
-        }
-
-        var value;
-        if (!code){
-            var o = relationOp(leftExpression.type(), rightExpression.type(), this.__relation, this.__relOps);
-            var oResult = o(leftExpression, rightExpression, this.language().rtl);
-            code = oResult.code();
-            value = oResult.constValue();
-        }
+        leftExpression = promoteTypeInExpression(leftExpression, rightExpression.type());
+        rightExpression = promoteTypeInExpression(rightExpression, leftExpression.type());
 
-        this.__expression = resultExpression 
-                          ? resultExpression
-                          : Code.makeExpression(code, basicTypes.bool, undefined, value);
+        var o = relationOp(leftExpression.type(), rightExpression.type(), this.__relation, this.__relOps, this);
+        this.__expression = o(leftExpression, rightExpression, this.language().rtl);
     },
     handleLiteral: function(relation){
         this.__relation = relation;

+ 6 - 6
src/eberon/EberonOperator.ob

@@ -41,27 +41,27 @@ PROCEDURE addStr*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PEx
 END addStr;
 
 PROCEDURE equalStr*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN Operator.binaryWithCode(left, right, rtl, opEqualStr, " == ", CodePrecedence.equal)
+    RETURN Operator.equal(left, right, rtl, opEqualStr, " == ")
 END equalStr;
 
 PROCEDURE notEqualStr*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN Operator.binaryWithCode(left, right, rtl, opNotEqualStr, " != ", CodePrecedence.equal)
+    RETURN Operator.equal(left, right, rtl, opNotEqualStr, " != ")
 END notEqualStr;
 
 PROCEDURE lessStr*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN Operator.binaryWithCode(left, right, rtl, opLessStr, " < ", CodePrecedence.relational)
+    RETURN Operator.relational(left, right, rtl, opLessStr, " < ")
 END lessStr;
 
 PROCEDURE greaterStr*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN Operator.binaryWithCode(left, right, rtl, opGreaterStr, " > ", CodePrecedence.relational)
+    RETURN Operator.relational(left, right, rtl, opGreaterStr, " > ")
 END greaterStr;
 
 PROCEDURE lessEqualStr*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN Operator.binaryWithCode(left, right, rtl, opLessEqualStr, " <= ", CodePrecedence.relational)
+    RETURN Operator.relational(left, right, rtl, opLessEqualStr, " <= ")
 END lessEqualStr;
 
 PROCEDURE greaterEqualStr*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN Operator.binaryWithCode(left, right, rtl, opGraterEqualStr, " >= ", CodePrecedence.relational)
+    RETURN Operator.relational(left, right, rtl, opGraterEqualStr, " >= ")
 END greaterEqualStr;
 
 END EberonOperator.

+ 44 - 25
src/ob/Operator.ob

@@ -161,6 +161,24 @@ PROCEDURE binaryWithCode*(
     RETURN binaryWithCodeEx(left, right, rtl, op, code, precedence, NIL, Precedence.none)
 END binaryWithCode;
 
+PROCEDURE relational*(
+    left, right: Code.PExpression; 
+    rtl: OberonRtl.PType;
+    op: BinaryOp;
+    code: STRING
+    ): Code.PExpression;
+    RETURN binaryWithCodeEx(left, right, rtl, op, code, Precedence.relational, Types.basic.bool, Precedence.none)
+END relational;
+
+PROCEDURE equal*(
+    left, right: Code.PExpression; 
+    rtl: OberonRtl.PType;
+    op: BinaryOp;
+    code: STRING
+    ): Code.PExpression;
+    RETURN binaryWithCodeEx(left, right, rtl, op, code, Precedence.equal, Types.basic.bool, Precedence.none)
+END equal;
+
 PROCEDURE promoteToWideIfNeeded(e: Code.PExpression): Code.PExpression;
 VAR
     result: Code.PExpression;
@@ -210,7 +228,7 @@ PROCEDURE binaryPred(
         op, 
         makePredCodeMaker(pred), 
         Precedence.none, 
-        NIL, 
+        Types.basic.bool, 
         Precedence.none
         )
 END binaryPred;
@@ -590,6 +608,16 @@ PROCEDURE setSymmetricDiff*(left, right: Code.PExpression; rtl: OberonRtl.PType)
     RETURN binaryWithCode(left, right, rtl, opSetSymmetricDiff, " ^ ", Precedence.bitXor)
 END setSymmetricDiff;
 
+PROCEDURE setHasBit*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
+    RETURN Code.makeExpressionWithPrecedence(
+            "1 << " + Code.adjustPrecedence(Code.derefExpression(left), Precedence.shift) 
+            + " & " + Code.adjustPrecedence(Code.derefExpression(right), Precedence.bitAnd),
+            Types.basic.bool,
+            NIL,
+            NIL,
+            Precedence.bitAnd)
+END setHasBit;
+
 PROCEDURE setInclL*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
     RETURN binaryPred(left, right, rtl, opSetInclL, codeSetInclL)
 END setInclL;
@@ -607,15 +635,15 @@ PROCEDURE and*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpre
 END and;
 
 PROCEDURE equalInt*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN binaryWithCode(left, right, rtl, opEqualInt, " == ", Precedence.equal)
+    RETURN equal(left, right, rtl, opEqualInt, " == ")
 END equalInt;
 
 PROCEDURE equalReal*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN binaryWithCode(left, right, rtl, opEqualReal, " == ", Precedence.equal)
+    RETURN equal(left, right, rtl, opEqualReal, " == ")
 END equalReal;
 
 PROCEDURE equalSet*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN binaryWithCode(left, right, rtl, opEqualSet, " == ", Precedence.equal)
+    RETURN equal(left, right, rtl, opEqualSet, " == ")
 END equalSet;
 
 PROCEDURE equalStr*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
@@ -623,15 +651,15 @@ PROCEDURE equalStr*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.P
 END equalStr;
 
 PROCEDURE notEqualInt*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN binaryWithCode(left, right, rtl, opNotEqualInt, " != ", Precedence.equal)
+    RETURN equal(left, right, rtl, opNotEqualInt, " != ")
 END notEqualInt;
 
 PROCEDURE notEqualReal*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN binaryWithCode(left, right, rtl, opNotEqualReal, " != ", Precedence.equal)
+    RETURN equal(left, right, rtl, opNotEqualReal, " != ")
 END notEqualReal;
 
 PROCEDURE notEqualSet*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN binaryWithCode(left, right, rtl, opNotEqualSet, " != ", Precedence.equal)
+    RETURN equal(left, right, rtl, opNotEqualSet, " != ")
 END notEqualSet;
 
 PROCEDURE notEqualStr*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
@@ -639,24 +667,15 @@ PROCEDURE notEqualStr*(left, right: Code.PExpression; rtl: OberonRtl.PType): Cod
 END notEqualStr;
 
 PROCEDURE is*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN binaryWithCodeEx(
-        left, 
-        right, 
-        rtl, 
-        NIL, 
-        " instanceof ", 
-        Precedence.relational, 
-        Types.basic.bool,
-        Precedence.none
-        )
+    RETURN relational(left, right, rtl, NIL, " instanceof ")
 END is;
 
 PROCEDURE lessInt*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN binaryWithCode(left, right, rtl, opLessInt, " < ", Precedence.relational)
+    RETURN relational(left, right, rtl, opLessInt, " < ")
 END lessInt;
 
 PROCEDURE lessReal*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN binaryWithCode(left, right, rtl, opLessReal, " < ", Precedence.relational)
+    RETURN relational(left, right, rtl, opLessReal, " < ")
 END lessReal;
 
 PROCEDURE lessStr*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
@@ -664,11 +683,11 @@ PROCEDURE lessStr*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PE
 END lessStr;
 
 PROCEDURE greaterInt*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN binaryWithCode(left, right, rtl, opGreaterInt, " > ", Precedence.relational)
+    RETURN relational(left, right, rtl, opGreaterInt, " > ")
 END greaterInt;
 
 PROCEDURE greaterReal*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN binaryWithCode(left, right, rtl, opGreaterReal, " > ", Precedence.relational)
+    RETURN relational(left, right, rtl, opGreaterReal, " > ")
 END greaterReal;
 
 PROCEDURE greaterStr*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
@@ -676,11 +695,11 @@ PROCEDURE greaterStr*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code
 END greaterStr;
 
 PROCEDURE eqLessInt*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN binaryWithCode(left, right, rtl, opEqLessInt, " <= ", Precedence.relational)
+    RETURN relational(left, right, rtl, opEqLessInt, " <= ")
 END eqLessInt;
 
 PROCEDURE eqLessReal*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN binaryWithCode(left, right, rtl, opEqLessReal, " <= ", Precedence.relational)
+    RETURN relational(left, right, rtl, opEqLessReal, " <= ")
 END eqLessReal;
 
 PROCEDURE eqLessStr*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
@@ -688,11 +707,11 @@ PROCEDURE eqLessStr*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.
 END eqLessStr;
 
 PROCEDURE eqGreaterInt*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN binaryWithCode(left, right, rtl, opEqGreaterInt, " >= ", Precedence.relational)
+    RETURN relational(left, right, rtl, opEqGreaterInt, " >= ")
 END eqGreaterInt;
 
 PROCEDURE eqGreaterReal*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
-    RETURN binaryWithCode(left, right, rtl, opEqGreaterReal, " >= ", Precedence.relational)
+    RETURN relational(left, right, rtl, opEqGreaterReal, " >= ")
 END eqGreaterReal;
 
 PROCEDURE eqGreaterStr*(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;