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; } }
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); }