protected override ICode VisitBinary(ExprBinary e) {
            var op = e.Op;
            var left = (Expr)this.Visit(e.Left);
            var right = (Expr)this.Visit(e.Right);
            var t = Tuple.Create(left, right);

            if (op == BinaryOp.Equal && TypeCombiner.Combine(e.Ctx, left, right).IsBoolean()) {
                if (left.IsLiteralBoolean(true)) {
                    return right;
                }
                if (right.IsLiteralBoolean(true)) {
                    return left;
                }
                if (left.IsLiteralBoolean(false)) {
                    return e.Ctx.ExprGen.NotAutoSimplify(right);
                }
                if (right.IsLiteralBoolean(false)) {
                    return e.Ctx.ExprGen.NotAutoSimplify(left);
                }
            }

            if (left != e.Left || right != e.Right) {
                return new ExprBinary(e.Ctx, op, e.Type, left, right);
            } else {
                return e;
            }
        }
Beispiel #2
0
 public static Expr op_Equality(ICall call) {
     var ctx = call.Ctx;
     var a = call.Args.ElementAt(0);
     var b = call.Args.ElementAt(1);
     var expr = new ExprBinary(ctx, BinaryOp.Equal, ctx.Boolean, a, b);
     return expr;
 }
 protected override ICode VisitBinary(ExprBinary e) {
     if (e.Op == BinaryOp.Equal || e.Op == BinaryOp.NotEqual) {
         if (e.Right.Type.IsBoolean() && !e.Left.Type.IsBoolean()) {
             return new ExprBinary(e.Ctx, e.Op, e.Type, this.ConvertToBoolean(e.Left), e.Right);
         } else if (e.Left.Type.IsBoolean() && !e.Right.Type.IsBoolean()) {
             return new ExprBinary(e.Ctx, e.Op, e.Type, e.Left, this.ConvertToBoolean(e.Right));
         }
     }
     return base.VisitBinary(e);
 }
 protected override ICode VisitBinary(ExprBinary e) {
     switch (e.Op) {
     case BinaryOp.And:
     case BinaryOp.Or:
         var leftPerms = VisitorCreatePerms.V(e.Left);
         var rightPerms = VisitorCreatePerms.V(e.Right);
         foreach (var l in leftPerms) {
             foreach (var r in rightPerms) {
                 foreach (var t in new[] { Tuple.Create(l, r), Tuple.Create(r, l) }) {
                     Expr perm;
                     if (t.Item1 == e.Left && t.Item2 == e.Right) {
                         perm = e;
                     } else {
                         perm = new ExprBinary(e.Ctx, e.Op, e.Type, t.Item1, t.Item2);
                     }
                     this.allPerms.Add((Expr)VisitorReplace.V(this.root, e, perm));
                 }
             }
         }
         break;
     }
     return e;
 }
 protected override ICode VisitUnary(ExprUnary e) {
     if (e.Expr.Type.IsInt64() || e.Expr.Type.IsUInt64()) {
         var ctx = e.Ctx;
         var signed = e.Expr.Type.IsInt64();
         Delegate d;
         switch (e.Op) {
         case UnaryOp.Negate:
             var zero = ctx.Literal(0L, ctx.Int64);
             var subCall = new ExprBinary(ctx, BinaryOp.Sub, ctx.Int64, zero, e.Expr);
             return subCall;
         case UnaryOp.BitwiseNot:
             d = signed ? (Delegate)(Func<Int64, Int64>)_Int64.BitwiseNot : (Func<UInt64, UInt64>)_UInt64.BitwiseNot;
             break;
         default:
             throw new NotImplementedException("Cannot handle: " + e.Op);
         }
         var m = ctx.Module.Import(d.Method);
         var expr = (Expr)this.Visit(e.Expr);
         var call = new ExprCall(ctx, m, null, expr);
         return call;
     }
     return base.VisitUnary(e);
 }
 protected override ICode VisitBinary(ExprBinary e) {
     var ctx = e.Ctx;
     // Special cases for == and != needed as an empty string is false, not true
     if (e.Op == BinaryOp.Equal) {
         if (e.Left.IsLiteralNull()) {
             if (e.Right.IsVar() && e.Right.Type.IsValueType && !e.Right.Type.IsNullable()) {
                 return ctx.Literal(false); // Non-nullable Value-type can never be null
             } else {
                 return new ExprJsExplicit(ctx, "(e == null)", ctx.Boolean, e.Right.Named("e"));
             }
         }
         if (e.Right.IsLiteralNull()) {
             if (e.Left.IsVar() && e.Left.Type.IsValueType && !e.Left.Type.IsNullable()) {
                 return ctx.Literal(false); // Non-nullable Value-type can never be null
             } else {
                 return new ExprJsExplicit(ctx, "(e == null)", ctx.Boolean, e.Left.Named("e"));
             }
         }
     }
     if (e.Op == BinaryOp.NotEqual || e.Op == BinaryOp.GreaterThan_Un) {
         if (e.Left.IsLiteralNull()) {
             if (e.Right.IsVar() && e.Right.Type.IsValueType && !e.Right.Type.IsNullable()) {
                 return ctx.Literal(true); // Non-nullable Value-type can never be null
             } else {
                 return new ExprJsExplicit(ctx, "(e != null)", ctx.Boolean, e.Right.Named("e"));
             }
         }
         if (e.Right.IsLiteralNull()) {
             if (e.Left.IsVar() && e.Left.Type.IsValueType && !e.Left.Type.IsNullable()) {
                 return ctx.Literal(true); // Non-nullable Value-type can never be null
             } else {
                 return new ExprJsExplicit(ctx, "(e != null)", ctx.Boolean, e.Left.Named("e"));
             }
         }
     }
     // Special case for eq and neq with unsigned integer types.
     // If either side of the eq/neq is unsigned, then ensure that both sides are unsigned
     if (e.Op == BinaryOp.Equal || e.Op == BinaryOp.NotEqual) {
         if (e.Left.Type.IsUnsignedInteger()) {
             if (e.Right.Type.IsSignedInteger()) {
                 return new ExprBinary(ctx, e.Op, e.Type, e.Left, new ExprConv(ctx, e.Right, e.Left.Type, false));
             }
         } else if (e.Right.Type.IsUnsignedInteger()) {
             if (e.Left.Type.IsSignedInteger()) {
                 return new ExprBinary(ctx, e.Op, e.Type, new ExprConv(ctx, e.Left, e.Right.Type, false), e.Right);
             }
         }
     }
     // Special case for unsigned <, <=, >, >=
     // Force conversions to unsigned if either side is signed
     if (e.Op == BinaryOp.LessThan_Un || e.Op == BinaryOp.LessThanOrEqual_Un ||
         e.Op == BinaryOp.GreaterThan_Un || e.Op == BinaryOp.GreaterThanOrEqual_Un) {
         Expr newLeft = null, newRight = null;
         if (e.Left.Type.IsSignedInteger()) {
             newLeft = new ExprConv(ctx, e.Left, e.Left.Type.UnsignedEquivilent(ctx.TypeSystem), false);
         }
         if (e.Right.Type.IsSignedInteger()) {
             newRight = new ExprConv(ctx, e.Right, e.Right.Type.UnsignedEquivilent(ctx.TypeSystem), false);
         }
         if (newLeft != null || newRight != null) {
             return new ExprBinary(ctx, e.Op, e.Type, newLeft ?? e.Left, newRight ?? e.Right);
         }
     }
     return base.VisitBinary(e);
 }
 public static Expr GetResourceFromDefault(ICall call) {
     var ctx = call.Ctx;
     var pre = new ExprLiteral(ctx, "GetResourceFromDefault_", ctx.String);
     var expr = new ExprBinary(ctx, BinaryOp.Add, ctx.String, pre, call.Args.First());
     return expr;
 }
 protected override ICode VisitBinary(ExprBinary e) {
     var forceInt = e.Op == BinaryOp.Div && e.Type.IsInteger();
     if (forceInt) {
         if (e.Type.IsUInt32()) {
             this.js.Append("(");
         } else {
             this.js.Append("(~~");
         }
     }
     this.js.Append("(");
     this.Visit(e.Left);
     this.js.AppendFormat(" {0} ", binaryOps[e.Op]);
     this.Visit(e.Right);
     this.js.Append(")");
     if (forceInt) {
         if (e.Type.IsUInt32()) {
             this.js.Append(">>>0");
         } else {
             this.js.Append(")");
         }
     }
     return e;
 }
 protected override ICode VisitBinary(ExprBinary e) {
     this.code.Append("(");
     this.Visit(e.Left);
     this.code.AppendFormat(" {0} ", binaryOps[e.Op]);
     this.Visit(e.Right);
     this.code.Append(")");
     return e;
 }
 private Stmt BrFalse(Instruction inst) {
     var expr = this.stack.Pop();
     if (expr.Type.IsString() || expr.Type.IsObject()) {
         // TODO: Move this JS-specific processing into a later, JS-specific stage
         // Special processing of string null-check required, as empty string == false in Javascript
         var check = new ExprBinary(this.ctx, BinaryOp.Equal, this.ctx.Boolean, expr, new ExprLiteral(this.ctx, null, this.ctx.String));
         return this.SsaInstResultAssignment(inst, check);
     } else {
         return this.SsaInstResultAssignment(inst, new ExprUnary(this.ctx, UnaryOp.Not, this.ctx.Boolean, expr));
     }
 }
 protected override ICode VisitBinary(ExprBinary e) {
     if (e.Left.Type.IsInt64() || e.Left.Type.IsUInt64()) {
         var ctx = e.Ctx;
         var signed = e.Left.Type.IsInt64();
         Delegate d;
         switch (e.Op) {
         case BinaryOp.Add:
             d = signed ? (Delegate)(Func<Int64, Int64, Int64>)_Int64.Add : (Func<UInt64, UInt64, UInt64>)_UInt64.Add;
             break;
         case BinaryOp.Sub:
             d = signed ? (Delegate)(Func<Int64, Int64, Int64>)_Int64.Subtract : (Func<UInt64, UInt64, UInt64>)_UInt64.Subtract;
             break;
         case BinaryOp.Mul:
             d = signed ? (Delegate)(Func<Int64, Int64, Int64>)_Int64.Multiply : (Func<UInt64, UInt64, UInt64>)_UInt64.Multiply;
             break;
         case BinaryOp.Div:
             d = (Func<Int64, Int64, Int64>)_Int64.Divide;
             break;
         case BinaryOp.Div_Un:
             d = (Func<UInt64, UInt64, UInt64>)_UInt64.Divide;
             break;
         case BinaryOp.Rem:
             d = (Func<Int64, Int64, Int64>)_Int64.Remainder;
             break;
         case BinaryOp.Rem_Un:
             d = (Func<UInt64, UInt64, UInt64>)_UInt64.Remainder;
             break;
         case BinaryOp.BitwiseAnd:
             d = signed ? (Delegate)(Func<Int64, Int64, Int64>)_Int64.BitwiseAnd : (Func<UInt64, UInt64, UInt64>)_UInt64.BitwiseAnd;
             break;
         case BinaryOp.BitwiseOr:
             d = signed ? (Delegate)(Func<Int64, Int64, Int64>)_Int64.BitwiseOr : (Func<UInt64, UInt64, UInt64>)_UInt64.BitwiseOr;
             break;
         case BinaryOp.BitwiseXor:
             d = signed ? (Delegate)(Func<Int64, Int64, Int64>)_Int64.BitwiseXor : (Func<UInt64, UInt64, UInt64>)_UInt64.BitwiseXor;
             break;
         case BinaryOp.Equal:
             d = signed ? (Delegate)(Func<Int64, Int64, bool>)_Int64.Equals_ : (Func<UInt64, UInt64, bool>)_UInt64.Equals_;
             break;
         case BinaryOp.NotEqual:
             d = signed ? (Delegate)(Func<Int64, Int64, bool>)_Int64.NotEquals : (Func<UInt64, UInt64, bool>)_UInt64.NotEquals;
             break;
         case BinaryOp.LessThan:
             d = (Func<Int64, Int64, bool>)_Int64.LessThan;
             break;
         case BinaryOp.LessThan_Un:
             d = (Func<UInt64, UInt64, bool>)_UInt64.LessThan;
             break;
         case BinaryOp.LessThanOrEqual:
             d = (Func<Int64, Int64, bool>)_Int64.LessThanOrEqual;
             break;
         case BinaryOp.LessThanOrEqual_Un:
             d = (Func<UInt64, UInt64, bool>)_UInt64.LessThanOrEqual;
             break;
         case BinaryOp.GreaterThan:
             d = (Func<Int64, Int64, bool>)_Int64.GreaterThan;
             break;
         case BinaryOp.GreaterThan_Un:
             d = (Func<UInt64, UInt64, bool>)_UInt64.GreaterThan;
             break;
         case BinaryOp.GreaterThanOrEqual:
             d = (Func<Int64, Int64, bool>)_Int64.GreaterThanOrEqual;
             break;
         case BinaryOp.GreaterThanOrEqual_Un:
             d = (Func<UInt64, UInt64, bool>)_UInt64.GreaterThanOrEqual;
             break;
         default:
             throw new NotImplementedException("Cannot handle: " + e.Op);
         }
         var m = ctx.Module.Import(d.Method);
         var left = (Expr)this.Visit(e.Left);
         var right = (Expr)this.Visit(e.Right);
         var call = new ExprCall(ctx, m, null, left, right);
         return call;
     }
     return base.VisitBinary(e);
 }