public override IExpression BinaryExpression(BinaryExpression binaryExpression) { var left = binaryExpression.Left.Accept(this); var right = binaryExpression.Right.Accept(this); if ( ( binaryExpression.ExpressionType == ExpressionType.Add && (left.Type == typeof(string) || right.Type == typeof(string)) ) || binaryExpression.ExpressionType == ExpressionType.Concat ) { return _resolver.ResolveMethod( new TypeAccess(typeof(string)), "Concat", FlattenConcatArguments(binaryExpression.Left, binaryExpression.Right) ); } else if (binaryExpression.ExpressionType == ExpressionType.Power) { return _resolver.ResolveMethod( new TypeAccess(typeof(Math)), "Pow", new[] { left, right } ); } else if (_resolver.DynamicExpression.Language == ExpressionLanguage.VisualBasic) { // Special handling for Visual Basic. string methodName = null; switch (binaryExpression.ExpressionType) { case ExpressionType.Compares: methodName = "CompareObjectEqual"; break; case ExpressionType.NotCompares: methodName = "CompareObjectNotEqual"; break; case ExpressionType.Greater: methodName = "CompareObjectGreater"; break; case ExpressionType.GreaterOrEquals: methodName = "CompareObjectGreaterEqual"; break; case ExpressionType.Less: methodName = "CompareObjectLess"; break; case ExpressionType.LessOrEquals: methodName = "CompareObjectLessEqual"; break; } // Is this an operator for which we have a method? if (methodName != null) { // Should we output a normal comparison anyway? if (TypeUtil.IsConvertible(left.Type) && TypeUtil.IsConvertible(right.Type)) { var expressionType = binaryExpression.ExpressionType; // Coerce Compares/NotCompares to Equals/NotEquals. if (expressionType == ExpressionType.Compares) expressionType = ExpressionType.Equals; else if (expressionType == ExpressionType.NotCompares) expressionType = ExpressionType.NotEquals; if ( left == binaryExpression.Left && right == binaryExpression.Right && expressionType == binaryExpression.ExpressionType ) return binaryExpression; else return new BinaryExpression(left, right, expressionType, binaryExpression.Type, binaryExpression.CommonType); } else { var method = typeof(Operators).GetMethod(methodName); Debug.Assert(method.ReturnType == typeof(object)); return new Cast( new MethodCall( new TypeAccess(typeof(Operators)), method, new[] { left, right, new Constant(false) } ), typeof(bool) ); } } } if (left == binaryExpression.Left && right == binaryExpression.Right) return binaryExpression; else return new BinaryExpression(left, right, binaryExpression.ExpressionType, binaryExpression.Type); }
private void BinaryLogicalExpression(BinaryExpression binaryExpression) { Label beforeLabel; Label afterLabel; switch (binaryExpression.ExpressionType) { case ExpressionType.And: case ExpressionType.LogicalAnd: beforeLabel = _il.DefineLabel(); afterLabel = _il.DefineLabel(); binaryExpression.Left.Accept(this); _il.Emit(OpCodes.Brfalse, beforeLabel); binaryExpression.Right.Accept(this); _il.Emit(OpCodes.Br, afterLabel); _il.MarkLabel(beforeLabel); ILUtil.EmitConstant(_il, 0); _il.MarkLabel(afterLabel); break; case ExpressionType.AndBoth: binaryExpression.Left.Accept(this); binaryExpression.Right.Accept(this); _il.Emit(OpCodes.And); break; case ExpressionType.Or: case ExpressionType.LogicalOr: beforeLabel = _il.DefineLabel(); afterLabel = _il.DefineLabel(); binaryExpression.Left.Accept(this); _il.Emit(OpCodes.Brtrue, beforeLabel); binaryExpression.Right.Accept(this); _il.Emit(OpCodes.Br, afterLabel); _il.MarkLabel(beforeLabel); ILUtil.EmitConstant(_il, 1); _il.MarkLabel(afterLabel); break; case ExpressionType.OrBoth: binaryExpression.Left.Accept(this); binaryExpression.Right.Accept(this); _il.Emit(OpCodes.Or); break; case ExpressionType.Xor: binaryExpression.Left.Accept(this); binaryExpression.Right.Accept(this); _il.Emit(OpCodes.Xor); break; default: throw new InvalidOperationException(); } }
private void BinaryShiftExpression(BinaryExpression binaryExpression) { binaryExpression.Left.Accept(this); binaryExpression.Right.Accept(this); int bits = Marshal.SizeOf(binaryExpression.Left.Type) * 8; ILUtil.EmitConstant(_il, bits - 1); _il.Emit(OpCodes.And); switch (binaryExpression.ExpressionType) { case ExpressionType.ShiftLeft: _il.Emit(OpCodes.Shl); break; case ExpressionType.ShiftRight: if (TypeUtil.IsUnsigned(binaryExpression.Left.Type)) _il.Emit(OpCodes.Shr_Un); else _il.Emit(OpCodes.Shr); break; default: throw new InvalidOperationException(); } }
private void BinaryBitwiseExpression(BinaryExpression binaryExpression) { Emit(binaryExpression.Left, binaryExpression.CommonType); Emit(binaryExpression.Right, binaryExpression.CommonType); switch (binaryExpression.ExpressionType) { case ExpressionType.And: case ExpressionType.BitwiseAnd: _il.Emit(OpCodes.And); break; case ExpressionType.Or: case ExpressionType.BitwiseOr: _il.Emit(OpCodes.Or); break; case ExpressionType.Xor: _il.Emit(OpCodes.Xor); break; } }
private void BinaryArithicExpression(BinaryExpression binaryExpression) { // Reference compares. if ( !binaryExpression.Left.Type.IsValueType && !binaryExpression.Right.Type.IsValueType && ( binaryExpression.ExpressionType == ExpressionType.Equals || binaryExpression.ExpressionType == ExpressionType.NotEquals ) ) { binaryExpression.Left.Accept(this); binaryExpression.Right.Accept(this); _il.Emit(OpCodes.Ceq); if (binaryExpression.ExpressionType == ExpressionType.NotEquals) { _il.Emit(OpCodes.Ldc_I4_0); _il.Emit(OpCodes.Ceq); } return; } Emit(binaryExpression.Left, binaryExpression.CommonType); Emit(binaryExpression.Right, binaryExpression.CommonType); switch (binaryExpression.ExpressionType) { case ExpressionType.Equals: case ExpressionType.NotEquals: _il.Emit(OpCodes.Ceq); if (binaryExpression.ExpressionType == ExpressionType.NotEquals) { _il.Emit(OpCodes.Ldc_I4_0); _il.Emit(OpCodes.Ceq); } break; case ExpressionType.Greater: case ExpressionType.LessOrEquals: if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) _il.Emit(OpCodes.Cgt_Un); else _il.Emit(OpCodes.Cgt); if (binaryExpression.ExpressionType == ExpressionType.LessOrEquals) { _il.Emit(OpCodes.Ldc_I4_0); _il.Emit(OpCodes.Ceq); } break; case ExpressionType.Less: case ExpressionType.GreaterOrEquals: if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) _il.Emit(OpCodes.Clt_Un); else _il.Emit(OpCodes.Clt); if (binaryExpression.ExpressionType == ExpressionType.GreaterOrEquals) { _il.Emit(OpCodes.Ldc_I4_0); _il.Emit(OpCodes.Ceq); } break; case ExpressionType.Add: if (_compiler._resolver.Options.Checked && TypeUtil.IsInteger(binaryExpression.CommonType)) { if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) _il.Emit(OpCodes.Add_Ovf_Un); else _il.Emit(OpCodes.Add_Ovf); } else { _il.Emit(OpCodes.Add); } break; case ExpressionType.Divide: if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) _il.Emit(OpCodes.Div_Un); else _il.Emit(OpCodes.Div); break; case ExpressionType.Multiply: if (_compiler._resolver.Options.Checked && TypeUtil.IsInteger(binaryExpression.CommonType)) { if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) _il.Emit(OpCodes.Mul_Ovf_Un); else _il.Emit(OpCodes.Mul_Ovf); } else { _il.Emit(OpCodes.Mul); } break; case ExpressionType.Subtract: if (_compiler._resolver.Options.Checked && TypeUtil.IsInteger(binaryExpression.CommonType)) { if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) _il.Emit(OpCodes.Sub_Ovf_Un); else _il.Emit(OpCodes.Sub_Ovf); } else { _il.Emit(OpCodes.Sub); } break; case ExpressionType.Modulo: if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) _il.Emit(OpCodes.Rem_Un); else _il.Emit(OpCodes.Rem); break; default: throw new InvalidOperationException(); } }
public void BinaryExpression(BinaryExpression binaryExpression) { switch (binaryExpression.ExpressionType) { case ExpressionType.Add: case ExpressionType.Divide: case ExpressionType.Multiply: case ExpressionType.Subtract: case ExpressionType.Equals: case ExpressionType.NotEquals: case ExpressionType.Greater: case ExpressionType.GreaterOrEquals: case ExpressionType.Less: case ExpressionType.LessOrEquals: case ExpressionType.Modulo: BinaryArithicExpression(binaryExpression); break; case ExpressionType.ShiftLeft: case ExpressionType.ShiftRight: BinaryShiftExpression(binaryExpression); break; case ExpressionType.And: case ExpressionType.Or: case ExpressionType.Xor: if (TypeUtil.IsInteger(binaryExpression.CommonType)) BinaryBitwiseExpression(binaryExpression); else BinaryLogicalExpression(binaryExpression); break; case ExpressionType.LogicalAnd: case ExpressionType.AndBoth: case ExpressionType.LogicalOr: case ExpressionType.OrBoth: BinaryLogicalExpression(binaryExpression); break; case ExpressionType.BitwiseAnd: case ExpressionType.BitwiseOr: BinaryBitwiseExpression(binaryExpression); break; default: throw new NotSupportedException(); } }
private void BinaryLogicalExpression(BinaryExpression binaryExpression) { Label beforeLabel; Label afterLabel; switch (binaryExpression.ExpressionType) { case ExpressionType.And: case ExpressionType.LogicalAnd: beforeLabel = _il.DefineLabel(); afterLabel = _il.DefineLabel(); binaryExpression.Left.Accept(this); _il.Emit(OpCodes.Brfalse, beforeLabel); binaryExpression.Right.Accept(this); _il.Emit(OpCodes.Br, afterLabel); _il.MarkLabel(beforeLabel); ILUtil.EmitConstant(_il, 0); _il.MarkLabel(afterLabel); break; case ExpressionType.AndBoth: binaryExpression.Left.Accept(this); binaryExpression.Right.Accept(this); _il.Emit(OpCodes.And); break; case ExpressionType.Or: case ExpressionType.LogicalOr: beforeLabel = _il.DefineLabel(); afterLabel = _il.DefineLabel(); binaryExpression.Left.Accept(this); _il.Emit(OpCodes.Brtrue, beforeLabel); binaryExpression.Right.Accept(this); _il.Emit(OpCodes.Br, afterLabel); _il.MarkLabel(beforeLabel); ILUtil.EmitConstant(_il, 1); _il.MarkLabel(afterLabel); break; case ExpressionType.OrBoth: binaryExpression.Left.Accept(this); binaryExpression.Right.Accept(this); _il.Emit(OpCodes.Or); break; case ExpressionType.Xor: binaryExpression.Left.Accept(this); binaryExpression.Right.Accept(this); _il.Emit(OpCodes.Xor); break; default: throw new InvalidOperationException(); } }
private void BinaryArithicExpression(BinaryExpression binaryExpression) { // Reference compares. if ( !binaryExpression.Left.Type.IsValueType && !binaryExpression.Right.Type.IsValueType && ( binaryExpression.ExpressionType == ExpressionType.Equals || binaryExpression.ExpressionType == ExpressionType.NotEquals ) ) { binaryExpression.Left.Accept(this); binaryExpression.Right.Accept(this); _il.Emit(OpCodes.Ceq); if (binaryExpression.ExpressionType == ExpressionType.NotEquals) { _il.Emit(OpCodes.Ldc_I4_0); _il.Emit(OpCodes.Ceq); } return; } Emit(binaryExpression.Left, binaryExpression.CommonType); Emit(binaryExpression.Right, binaryExpression.CommonType); switch (binaryExpression.ExpressionType) { case ExpressionType.Equals: case ExpressionType.NotEquals: _il.Emit(OpCodes.Ceq); if (binaryExpression.ExpressionType == ExpressionType.NotEquals) { _il.Emit(OpCodes.Ldc_I4_0); _il.Emit(OpCodes.Ceq); } break; case ExpressionType.Greater: case ExpressionType.LessOrEquals: if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) { _il.Emit(OpCodes.Cgt_Un); } else { _il.Emit(OpCodes.Cgt); } if (binaryExpression.ExpressionType == ExpressionType.LessOrEquals) { _il.Emit(OpCodes.Ldc_I4_0); _il.Emit(OpCodes.Ceq); } break; case ExpressionType.Less: case ExpressionType.GreaterOrEquals: if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) { _il.Emit(OpCodes.Clt_Un); } else { _il.Emit(OpCodes.Clt); } if (binaryExpression.ExpressionType == ExpressionType.GreaterOrEquals) { _il.Emit(OpCodes.Ldc_I4_0); _il.Emit(OpCodes.Ceq); } break; case ExpressionType.Add: if (_compiler._resolver.Options.Checked && TypeUtil.IsInteger(binaryExpression.CommonType)) { if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) { _il.Emit(OpCodes.Add_Ovf_Un); } else { _il.Emit(OpCodes.Add_Ovf); } } else { _il.Emit(OpCodes.Add); } break; case ExpressionType.Divide: if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) { _il.Emit(OpCodes.Div_Un); } else { _il.Emit(OpCodes.Div); } break; case ExpressionType.Multiply: if (_compiler._resolver.Options.Checked && TypeUtil.IsInteger(binaryExpression.CommonType)) { if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) { _il.Emit(OpCodes.Mul_Ovf_Un); } else { _il.Emit(OpCodes.Mul_Ovf); } } else { _il.Emit(OpCodes.Mul); } break; case ExpressionType.Subtract: if (_compiler._resolver.Options.Checked && TypeUtil.IsInteger(binaryExpression.CommonType)) { if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) { _il.Emit(OpCodes.Sub_Ovf_Un); } else { _il.Emit(OpCodes.Sub_Ovf); } } else { _il.Emit(OpCodes.Sub); } break; case ExpressionType.Modulo: if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) { _il.Emit(OpCodes.Rem_Un); } else { _il.Emit(OpCodes.Rem); } break; default: throw new InvalidOperationException(); } }