Exemple #1
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();
                }
            }
Exemple #2
0
            public void UnaryExpression(UnaryExpression unaryExpression)
            {
                switch (unaryExpression.ExpressionType)
                {
                case ExpressionType.Minus:
                    unaryExpression.Operand.Accept(this);

                    _il.Emit(OpCodes.Neg);
                    break;

                case ExpressionType.Not:
                    unaryExpression.Operand.Accept(this);

                    if (TypeUtil.IsInteger(unaryExpression.Operand.Type))
                    {
                        _il.Emit(OpCodes.Not);
                    }
                    else
                    {
                        ILUtil.EmitConstant(_il, 0);
                        _il.Emit(OpCodes.Ceq);
                    }
                    break;

                case ExpressionType.LogicalNot:
                    unaryExpression.Operand.Accept(this);

                    ILUtil.EmitConstant(_il, 0);
                    _il.Emit(OpCodes.Ceq);
                    break;

                case ExpressionType.BitwiseNot:
                    unaryExpression.Operand.Accept(this);

                    _il.Emit(OpCodes.Not);
                    break;

                case ExpressionType.Plus:
                case ExpressionType.Group:
                    // No-ops.

                    unaryExpression.Operand.Accept(this);
                    break;

                default:
                    throw new NotSupportedException();
                }
            }
Exemple #3
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();
                }
            }
Exemple #4
0
        private Type ResolveExpressionType(Type left, Type right, Type commonType, ExpressionType type)
        {
            Require.NotNull(left, "left");
            Require.NotNull(right, "right");

            // TODO: Implicit/explicit operators and operators for the expression type.

            // Boolean operators.

            switch (type)
            {
            case ExpressionType.And:
            case ExpressionType.Or:
            case ExpressionType.Xor:
            case ExpressionType.AndBoth:
            case ExpressionType.OrBoth:
                if (TypeUtil.IsInteger(commonType))
                {
                    return(commonType);
                }

                else if (left != typeof(bool) || right != typeof(bool))
                {
                    throw new ExpressionsException("Invalid operand for expression type", ExpressionsExceptionType.TypeMismatch);
                }

                return(typeof(bool));

            case ExpressionType.Greater:
            case ExpressionType.GreaterOrEquals:
            case ExpressionType.Less:
            case ExpressionType.LessOrEquals:
                if (
                    !(left.IsEnum || TypeUtil.IsNumeric(left)) ||
                    !(right.IsEnum || TypeUtil.IsNumeric(right))
                    )
                {
                    throw new ExpressionsException("Invalid operand for expression type", ExpressionsExceptionType.TypeMismatch);
                }

                return(typeof(bool));

            case ExpressionType.Equals:
            case ExpressionType.NotEquals:
            case ExpressionType.In:
            case ExpressionType.LogicalAnd:
            case ExpressionType.LogicalOr:
            case ExpressionType.Compares:
            case ExpressionType.NotCompares:
                return(typeof(bool));

            case ExpressionType.Add:
                if (
                    !(left == typeof(string) || right == typeof(string)) &&
                    !(TypeUtil.IsNumeric(left) && TypeUtil.IsNumeric(right))
                    )
                {
                    throw new ExpressionsException("Invalid operand for expression type", ExpressionsExceptionType.TypeMismatch);
                }

                return(commonType);

            case ExpressionType.Subtract:
            case ExpressionType.Multiply:
            case ExpressionType.Divide:
            case ExpressionType.Power:
                if (!TypeUtil.IsNumeric(left) || !TypeUtil.IsNumeric(right))
                {
                    throw new ExpressionsException("Invalid operand for expression type", ExpressionsExceptionType.TypeMismatch);
                }

                return(commonType);

            default:
                return(commonType);
            }
        }
Exemple #5
0
 private bool IsAllowableImplicit(Type a, Type b)
 {
     return(TypeUtil.IsInteger(a) == TypeUtil.IsInteger(b));
 }
Exemple #6
0
        public IExpression UnaryExpression(Ast.UnaryExpression unaryExpression)
        {
            var operand = unaryExpression.Operand.Accept(this);

            string operatorName = null;

            switch (unaryExpression.Type)
            {
            case ExpressionType.Plus: operatorName = "op_UnaryPlus"; break;

            case ExpressionType.Minus: operatorName = "op_UnaryNegation"; break;

            case ExpressionType.Not:
            case ExpressionType.LogicalNot:
                operatorName = "op_Negation"; break;
            }

            if (operatorName != null)
            {
                var method = _resolver.FindOperatorMethod(
                    operatorName,
                    new[] { operand.Type },
                    null,
                    new[] { operand.Type }
                    );

                if (method != null)
                {
                    return(new Expressions.MethodCall(
                               new TypeAccess(method.DeclaringType),
                               method,
                               new[]
                    {
                        operand
                    }
                               ));
                }
            }

            Type type;

            switch (unaryExpression.Type)
            {
            case ExpressionType.Plus:
                if (!TypeUtil.IsValidUnaryArgument(operand.Type))
                {
                    throw new ExpressionsException("Operand of plus operation must be an integer type", ExpressionsExceptionType.TypeMismatch);
                }

                type = operand.Type;
                break;

            case ExpressionType.Group:
                type = operand.Type;
                break;

            case ExpressionType.Minus:
                if (!TypeUtil.IsValidUnaryArgument(operand.Type))
                {
                    throw new ExpressionsException("Operand of minus operation must be an integer type", ExpressionsExceptionType.TypeMismatch);
                }

                // TODO: Make constants signed and handle minus on unsigned's.

                type = operand.Type;
                break;

            case ExpressionType.LogicalNot:
                if (operand.Type != typeof(bool))
                {
                    throw new ExpressionsException("Operand of not operation must be a boolean type", ExpressionsExceptionType.TypeMismatch);
                }

                type = typeof(bool);
                break;

            case ExpressionType.BitwiseNot:
                if (!TypeUtil.IsInteger(operand.Type))
                {
                    throw new ExpressionsException(
                              "Cannot not bitwise not boolean types",
                              ExpressionsExceptionType.TypeMismatch
                              );
                }

                type = operand.Type;
                break;

            case ExpressionType.Not:
                if (TypeUtil.IsInteger(operand.Type))
                {
                    type = operand.Type;
                }
                else
                {
                    if (operand.Type != typeof(bool))
                    {
                        throw new ExpressionsException("Operand of not operation must be a boolean type", ExpressionsExceptionType.TypeMismatch);
                    }

                    type = typeof(bool);
                }
                break;

            default:
                throw new InvalidOperationException();
            }

            return(new Expressions.UnaryExpression(operand, type, unaryExpression.Type));
        }
Exemple #7
0
        public IExpression BinaryExpression(Ast.BinaryExpression binaryExpression)
        {
            // In expressions are converted to method calls.

            if (binaryExpression.Type == ExpressionType.In)
            {
                return(BinaryInExpression(binaryExpression));
            }

            // We need to do this here and not in the conversion phase because
            // we need the return type of the method to fully bind the tree.

            var left  = binaryExpression.Left.Accept(this);
            var right = binaryExpression.Right.Accept(this);

            string operatorName = null;

            switch (binaryExpression.Type)
            {
            case ExpressionType.Add: operatorName = "op_Addition"; break;

            case ExpressionType.Divide: operatorName = "op_Division"; break;

            case ExpressionType.Multiply: operatorName = "op_Multiply"; break;

            case ExpressionType.Subtract: operatorName = "op_Subtraction"; break;

            case ExpressionType.Equals: operatorName = "op_Equality"; break;

            case ExpressionType.NotEquals: operatorName = "op_Inequality"; break;

            case ExpressionType.Greater: operatorName = "op_GreaterThan"; break;

            case ExpressionType.GreaterOrEquals: operatorName = "op_GreaterThanOrEqual"; break;

            case ExpressionType.Less: operatorName = "op_LessThan"; break;

            case ExpressionType.LessOrEquals: operatorName = "op_LessThanOrEqual"; break;

            case ExpressionType.ShiftLeft: operatorName = "op_LeftShift"; break;

            case ExpressionType.ShiftRight: operatorName = "op_RightShift"; break;

            case ExpressionType.Modulo: operatorName = "op_Modulus"; break;

            case ExpressionType.LogicalAnd: operatorName = "op_LogicalAnd"; break;

            case ExpressionType.AndBoth: operatorName = "op_LogicalAnd"; break;

            case ExpressionType.LogicalOr: operatorName = "op_LogicalOr"; break;

            case ExpressionType.OrBoth: operatorName = "op_LogicalOr"; break;

            case ExpressionType.BitwiseAnd: operatorName = "op_BitwiseAnd"; break;

            case ExpressionType.BitwiseOr: operatorName = "op_BitwiseOr"; break;

            case ExpressionType.And:
                if (left.Type == typeof(bool) && right.Type == typeof(bool))
                {
                    operatorName = "op_LogicalAnd";
                }
                else
                {
                    operatorName = "op_BitwiseAnd";
                }
                break;

            case ExpressionType.Or:
                if (left.Type == typeof(bool) && right.Type == typeof(bool))
                {
                    operatorName = "op_LogicalOr";
                }
                else
                {
                    operatorName = "op_BitwiseOr";
                }
                break;

            case ExpressionType.Xor:
                operatorName = "op_ExclusiveOr";
                break;
            }

            if (operatorName != null)
            {
                var method = _resolver.FindOperatorMethod(
                    operatorName,
                    new[] { left.Type, right.Type },
                    null,
                    new[] { left.Type, right.Type },
                    new[] { left is Expressions.Constant && ((Expressions.Constant)left).Value == null, right is Expressions.Constant && ((Expressions.Constant)right).Value == null }
                    );

                if (method != null)
                {
                    return(new Expressions.MethodCall(
                               new TypeAccess(typeof(string)),
                               method,
                               new[]
                    {
                        left,
                        right
                    }
                               ));
                }
            }

            Type commonType;

            switch (binaryExpression.Type)
            {
            case ExpressionType.ShiftLeft:
            case ExpressionType.ShiftRight:
                if (!TypeUtil.IsInteger(left.Type))
                {
                    throw new ExpressionsException("Left operand of shift operations must be of an integer type", ExpressionsExceptionType.TypeMismatch);
                }
                if (right.Type != typeof(int) && right.Type != typeof(byte))
                {
                    throw new ExpressionsException("Right operand of shift operations must be integer or byte type", ExpressionsExceptionType.TypeMismatch);
                }
                commonType = left.Type;
                break;

            case ExpressionType.Power:
                commonType = typeof(double);
                break;

            case ExpressionType.Greater:
            case ExpressionType.GreaterOrEquals:
            case ExpressionType.Less:
            case ExpressionType.LessOrEquals:
                commonType = ResolveExpressionCommonType(left.Type, right.Type, false, true, false);
                break;

            case ExpressionType.Equals:
            case ExpressionType.NotEquals:
            case ExpressionType.Compares:
            case ExpressionType.NotCompares:
                if (left.Type.IsValueType != right.Type.IsValueType)
                {
                    throw new ExpressionsException("Cannot resolve expression type", ExpressionsExceptionType.TypeMismatch);
                }

                commonType = ResolveExpressionCommonType(left.Type, right.Type, false, false, true);
                break;

            default:
                commonType = ResolveExpressionCommonType(left.Type, right.Type, binaryExpression.Type == ExpressionType.Add, false, false);
                break;
            }

            var type = ResolveExpressionType(left.Type, right.Type, commonType, binaryExpression.Type);

            var expressionType = binaryExpression.Type;

            if (type != typeof(bool))
            {
                if (expressionType == ExpressionType.AndBoth)
                {
                    expressionType = ExpressionType.BitwiseAnd;
                }
                else if (expressionType == ExpressionType.OrBoth)
                {
                    expressionType = ExpressionType.BitwiseOr;
                }
            }

            return(new Expressions.BinaryExpression(left, right, expressionType, type, commonType));
        }