예제 #1
0
        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);
        }
예제 #2
0
            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();
                }
            }
예제 #3
0
            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();
                }
            }
예제 #4
0
            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;
                }
            }
예제 #5
0
            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();
                }
            }
예제 #6
0
            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();
                }
            }
예제 #7
0
            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();
                }
            }
예제 #8
0
            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();
                }
            }