protected internal Binary(NRefactory.BinaryOperatorExpression binaryOperatorExpression, IScope scope, INRefcatoryExpressionVisitor visitor)
            : base(scope, visitor) {

            _binaryOperatorExpression = binaryOperatorExpression;
            Left = binaryOperatorExpression.Left.AcceptVisitor(Visitor, ParentScope);
            Right = binaryOperatorExpression.Right.AcceptVisitor(Visitor, ParentScope);
            _binaryOperationType = GetBinaryOperator(binaryOperatorExpression.Operator);
            _promotionDecisions = BinaryNumericPromotionDecision.Decide(Left.Type, Right.Type);
            InternalType = binaryOperatorExpression.GetBinaryOperationType(_promotionDecisions, Left.Type);
        }
 protected internal Binary(NRefactory.BinaryOperatorExpression binaryOperatorExpression, IScope scope, INRefcatoryExpressionVisitor visitor)
     : base(scope, visitor)
 {
     _binaryOperatorExpression = binaryOperatorExpression;
     Left  = binaryOperatorExpression.Left.AcceptVisitor(Visitor, ParentScope);
     Right = binaryOperatorExpression.Right.AcceptVisitor(Visitor, ParentScope);
     _binaryOperationType = GetBinaryOperator(binaryOperatorExpression.Operator);
     _promotionDecisions  = BinaryNumericPromotionDecision.Decide(Left.Type, Right.Type);
     InternalType         = binaryOperatorExpression.GetBinaryOperationType(_promotionDecisions, Left.Type);
 }
        private object EvaluateBinaryOperatorExpression(ICSharpCode.NRefactory.CSharp.Expression result, CodeContext codeContext)
        {
            ICSharpCode.NRefactory.CSharp.BinaryOperatorExpression binaryExpression = result as
                                                                                      ICSharpCode.NRefactory.CSharp.BinaryOperatorExpression;

            object left  = EvaluateExpression(binaryExpression.Left, codeContext);
            object right = EvaluateExpression(binaryExpression.Right, codeContext);

            switch (binaryExpression.Operator)
            {
            case BinaryOperatorType.Add:
                return(PrimitiveOperationManager.Self.AddObjects(left, right));

            case BinaryOperatorType.ConditionalAnd:
                return((bool)left && (bool)right);

            case BinaryOperatorType.ConditionalOr:
                return((bool)left || (bool)right);

            case BinaryOperatorType.Divide:
                return(PrimitiveOperationManager.Self.DivideObjects(left, right));

            case BinaryOperatorType.Equality:
                return(left == right);

            case BinaryOperatorType.GreaterThan:
                return(PrimitiveOperationManager.Self.GreaterThan(left, right));

            case BinaryOperatorType.GreaterThanOrEqual:
                return(left == right ||
                       PrimitiveOperationManager.Self.GreaterThan(left, right));

            case BinaryOperatorType.InEquality:
                return(left != right);

            case BinaryOperatorType.LessThan:
                return(PrimitiveOperationManager.Self.LessThan(left, right));

            case BinaryOperatorType.LessThanOrEqual:
                return(left == right ||
                       PrimitiveOperationManager.Self.LessThan(left, right));

            case BinaryOperatorType.Multiply:
                return(PrimitiveOperationManager.Self.MultiplyObjects(left, right));

            case BinaryOperatorType.Subtract:
                return(PrimitiveOperationManager.Self.SubtractObjects(left, right));

            default:
                return(null);
            }
        }
Example #4
0
 public static Binary Binary(NRefactory.BinaryOperatorExpression binaryOperatorExpression, IScope scope, INRefcatoryExpressionVisitor visitor)
 {
     return(new Binary(binaryOperatorExpression, scope, visitor));
 }
        AstNode TransformByteCode(ILExpression byteCode)
        {
            object operand = byteCode.Operand;
            AstType operandAsTypeRef = AstBuilder.ConvertType(operand as Cecil.TypeReference);

            List<Ast.Expression> args = new List<Expression>();
            foreach(ILExpression arg in byteCode.Arguments) {
                args.Add((Ast.Expression)TransformExpression(arg));
            }
            Ast.Expression arg1 = args.Count >= 1 ? args[0] : null;
            Ast.Expression arg2 = args.Count >= 2 ? args[1] : null;
            Ast.Expression arg3 = args.Count >= 3 ? args[2] : null;

            switch (byteCode.Code) {
                    #region Arithmetic
                case ILCode.Add:
                case ILCode.Add_Ovf:
                case ILCode.Add_Ovf_Un:
                    {
                        BinaryOperatorExpression boe;
                        if (byteCode.InferredType is PointerType) {
                            if (byteCode.Arguments[0].ExpectedType is PointerType) {
                                arg2 = DivideBySize(arg2, ((PointerType)byteCode.InferredType).ElementType);
                                boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
                                boe.AddAnnotation(IntroduceUnsafeModifier.PointerArithmeticAnnotation);
                            } else if (byteCode.Arguments[1].ExpectedType is PointerType) {
                                arg1 = DivideBySize(arg1, ((PointerType)byteCode.InferredType).ElementType);
                                boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
                                boe.AddAnnotation(IntroduceUnsafeModifier.PointerArithmeticAnnotation);
                            } else {
                                boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
                            }
                        } else {
                            boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
                        }
                        boe.AddAnnotation(byteCode.Code == ILCode.Add ? AddCheckedBlocks.UncheckedAnnotation : AddCheckedBlocks.CheckedAnnotation);
                        return boe;
                    }
                case ILCode.Sub:
                case ILCode.Sub_Ovf:
                case ILCode.Sub_Ovf_Un:
                    {
                        BinaryOperatorExpression boe;
                        if (byteCode.InferredType is PointerType) {
                            if (byteCode.Arguments[0].ExpectedType is PointerType) {
                                arg2 = DivideBySize(arg2, ((PointerType)byteCode.InferredType).ElementType);
                                boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
                                boe.WithAnnotation(IntroduceUnsafeModifier.PointerArithmeticAnnotation);
                            } else {
                                boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
                            }
                        } else {
                            boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
                        }
                        boe.AddAnnotation(byteCode.Code == ILCode.Sub ? AddCheckedBlocks.UncheckedAnnotation : AddCheckedBlocks.CheckedAnnotation);
                        return boe;
                    }
                    case ILCode.Div:        return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2);
                    case ILCode.Div_Un:     return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2);
                    case ILCode.Mul:        return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2).WithAnnotation(AddCheckedBlocks.UncheckedAnnotation);
                    case ILCode.Mul_Ovf:    return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2).WithAnnotation(AddCheckedBlocks.CheckedAnnotation);
                    case ILCode.Mul_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2).WithAnnotation(AddCheckedBlocks.CheckedAnnotation);
                    case ILCode.Rem:        return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2);
                    case ILCode.Rem_Un:     return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2);
                    case ILCode.And:        return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseAnd, arg2);
                    case ILCode.Or:         return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseOr, arg2);
                    case ILCode.Xor:        return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ExclusiveOr, arg2);
                    case ILCode.Shl:        return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftLeft, arg2);
                    case ILCode.Shr:        return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2);
                    case ILCode.Shr_Un:     return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2);
                    case ILCode.Neg:        return new Ast.UnaryOperatorExpression(UnaryOperatorType.Minus, arg1).WithAnnotation(AddCheckedBlocks.UncheckedAnnotation);
                    case ILCode.Not:        return new Ast.UnaryOperatorExpression(UnaryOperatorType.BitNot, arg1);
                case ILCode.PostIncrement:
                case ILCode.PostIncrement_Ovf:
                case ILCode.PostIncrement_Ovf_Un:
                    {
                        if (arg1 is DirectionExpression)
                            arg1 = ((DirectionExpression)arg1).Expression.Detach();
                        var uoe = new Ast.UnaryOperatorExpression(
                            (int)byteCode.Operand > 0 ? UnaryOperatorType.PostIncrement : UnaryOperatorType.PostDecrement, arg1);
                        uoe.AddAnnotation((byteCode.Code == ILCode.PostIncrement) ? AddCheckedBlocks.UncheckedAnnotation : AddCheckedBlocks.CheckedAnnotation);
                        return uoe;
                    }
                    #endregion
                    #region Arrays
                    case ILCode.Newarr: {
                        var ace = new Ast.ArrayCreateExpression();
                        ace.Type = operandAsTypeRef;
                        ComposedType ct = operandAsTypeRef as ComposedType;
                        if (ct != null) {
                            // change "new (int[,])[10] to new int[10][,]"
                            ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers);
                        }
                        if (byteCode.Code == ILCode.InitArray) {
                            ace.Initializer = new ArrayInitializerExpression();
                            ace.Initializer.Elements.AddRange(args);
                        } else {
                            ace.Arguments.Add(arg1);
                        }
                        return ace;
                    }
                    case ILCode.InitArray: {
                        var ace = new Ast.ArrayCreateExpression();
                        ace.Type = operandAsTypeRef;
                        ComposedType ct = operandAsTypeRef as ComposedType;
                        var arrayType = (ArrayType) operand;
                        if (ct != null)
                        {
                            // change "new (int[,])[10] to new int[10][,]"
                            ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers);
                            ace.Initializer = new ArrayInitializerExpression();
                        }
                        var newArgs = new List<Expression>();
                        foreach (var arrayDimension in arrayType.Dimensions.Skip(1).Reverse())
                        {
                            int length = (int)arrayDimension.UpperBound - (int)arrayDimension.LowerBound;
                            for (int j = 0; j < args.Count; j += length)
                            {
                                var child = new ArrayInitializerExpression();
                                child.Elements.AddRange(args.GetRange(j, length));
                                newArgs.Add(child);
                            }
                            var temp = args;
                            args = newArgs;
                            newArgs = temp;
                            newArgs.Clear();
                        }
                        ace.Initializer.Elements.AddRange(args);
                        return ace;
                    }
                    case ILCode.Ldlen: return arg1.Member("Length");
                case ILCode.Ldelem_I:
                case ILCode.Ldelem_I1:
                case ILCode.Ldelem_I2:
                case ILCode.Ldelem_I4:
                case ILCode.Ldelem_I8:
                case ILCode.Ldelem_U1:
                case ILCode.Ldelem_U2:
                case ILCode.Ldelem_U4:
                case ILCode.Ldelem_R4:
                case ILCode.Ldelem_R8:
                case ILCode.Ldelem_Ref:
                case ILCode.Ldelem_Any:
                    return arg1.Indexer(arg2);
                case ILCode.Ldelema:
                    return MakeRef(arg1.Indexer(arg2));
                case ILCode.Stelem_I:
                case ILCode.Stelem_I1:
                case ILCode.Stelem_I2:
                case ILCode.Stelem_I4:
                case ILCode.Stelem_I8:
                case ILCode.Stelem_R4:
                case ILCode.Stelem_R8:
                case ILCode.Stelem_Ref:
                case ILCode.Stelem_Any:
                    return new Ast.AssignmentExpression(arg1.Indexer(arg2), arg3);
                case ILCode.CompoundAssignment:
                    {
                        CastExpression cast = arg1 as CastExpression;
                        var boe = cast != null ? (BinaryOperatorExpression)cast.Expression : arg1 as BinaryOperatorExpression;
                        // AssignmentExpression doesn't support overloaded operators so they have to be processed to BinaryOperatorExpression
                        if (boe == null) {
                            var tmp = new ParenthesizedExpression(arg1);
                            ReplaceMethodCallsWithOperators.ProcessInvocationExpression((InvocationExpression)arg1);
                            boe = (BinaryOperatorExpression)tmp.Expression;
                        }
                        var assignment = new Ast.AssignmentExpression {
                            Left = boe.Left.Detach(),
                            Operator = ReplaceMethodCallsWithOperators.GetAssignmentOperatorForBinaryOperator(boe.Operator),
                            Right = boe.Right.Detach()
                        }.CopyAnnotationsFrom(boe);
                        // We do not mark the resulting assignment as RestoreOriginalAssignOperatorAnnotation, because
                        // the operator cannot be translated back to the expanded form (as the left-hand expression
                        // would be evaluated twice, and might have side-effects)
                        if (cast != null) {
                            cast.Expression = assignment;
                            return cast;
                        } else {
                            return assignment;
                        }
                    }
                    #endregion
                    #region Comparison
                    case ILCode.Ceq: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2);
                    case ILCode.Cne: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2);
                    case ILCode.Cgt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2);
                    case ILCode.Cgt_Un: {
                        // can also mean Inequality, when used with object references
                        TypeReference arg1Type = byteCode.Arguments[0].InferredType;
                        if (arg1Type != null && !arg1Type.IsValueType) goto case ILCode.Cne;
                        goto case ILCode.Cgt;
                    }
                    case ILCode.Cle_Un: {
                        // can also mean Equality, when used with object references
                        TypeReference arg1Type = byteCode.Arguments[0].InferredType;
                        if (arg1Type != null && !arg1Type.IsValueType) goto case ILCode.Ceq;
                        goto case ILCode.Cle;
                    }
                    case ILCode.Cle: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2);
                case ILCode.Cge_Un:
                    case ILCode.Cge: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2);
                case ILCode.Clt_Un:
                    case ILCode.Clt:    return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2);
                    #endregion
                    #region Logical
                    case ILCode.LogicNot:   return new Ast.UnaryOperatorExpression(UnaryOperatorType.Not, arg1);
                    case ILCode.LogicAnd:   return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ConditionalAnd, arg2);
                    case ILCode.LogicOr:    return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ConditionalOr, arg2);
                    case ILCode.TernaryOp:  return new Ast.ConditionalExpression() { Condition = arg1, TrueExpression = arg2, FalseExpression = arg3 };
                    case ILCode.NullCoalescing: 	return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.NullCoalescing, arg2);
                    #endregion
                    #region Branch
                    case ILCode.Br:         return new Ast.GotoStatement(((ILLabel)byteCode.Operand).Name);
                case ILCode.Brtrue:
                    return new Ast.IfElseStatement() {
                        Condition = arg1,
                        TrueStatement = new BlockStatement() {
                            new Ast.GotoStatement(((ILLabel)byteCode.Operand).Name)
                        }
                    };
                    case ILCode.LoopOrSwitchBreak: return new Ast.BreakStatement();
                    case ILCode.LoopContinue:      return new Ast.ContinueStatement();
                    #endregion
                    #region Conversions
                case ILCode.Conv_I1:
                case ILCode.Conv_I2:
                case ILCode.Conv_I4:
                case ILCode.Conv_I8:
                case ILCode.Conv_U1:
                case ILCode.Conv_U2:
                case ILCode.Conv_U4:
                case ILCode.Conv_U8:
                case ILCode.Conv_I:
                case ILCode.Conv_U:
                    {
                        // conversion was handled by Convert() function using the info from type analysis
                        CastExpression cast = arg1 as CastExpression;
                        if (cast != null) {
                            cast.AddAnnotation(AddCheckedBlocks.UncheckedAnnotation);
                        }
                        return arg1;
                    }
                case ILCode.Conv_R4:
                case ILCode.Conv_R8:
                case ILCode.Conv_R_Un: // TODO
                    return arg1;
                case ILCode.Conv_Ovf_I1:
                case ILCode.Conv_Ovf_I2:
                case ILCode.Conv_Ovf_I4:
                case ILCode.Conv_Ovf_I8:
                case ILCode.Conv_Ovf_U1:
                case ILCode.Conv_Ovf_U2:
                case ILCode.Conv_Ovf_U4:
                case ILCode.Conv_Ovf_U8:
                case ILCode.Conv_Ovf_I1_Un:
                case ILCode.Conv_Ovf_I2_Un:
                case ILCode.Conv_Ovf_I4_Un:
                case ILCode.Conv_Ovf_I8_Un:
                case ILCode.Conv_Ovf_U1_Un:
                case ILCode.Conv_Ovf_U2_Un:
                case ILCode.Conv_Ovf_U4_Un:
                case ILCode.Conv_Ovf_U8_Un:
                case ILCode.Conv_Ovf_I:
                case ILCode.Conv_Ovf_U:
                case ILCode.Conv_Ovf_I_Un:
                case ILCode.Conv_Ovf_U_Un:
                    {
                        // conversion was handled by Convert() function using the info from type analysis
                        CastExpression cast = arg1 as CastExpression;
                        if (cast != null) {
                            cast.AddAnnotation(AddCheckedBlocks.CheckedAnnotation);
                        }
                        return arg1;
                    }
                case ILCode.Unbox_Any:
                    // unboxing does not require a cast if the argument was an isinst instruction
                    if (arg1 is AsExpression && byteCode.Arguments[0].Code == ILCode.Isinst && TypeAnalysis.IsSameType(operand as TypeReference, byteCode.Arguments[0].Operand as TypeReference))
                        return arg1;
                    else
                        goto case ILCode.Castclass;
                case ILCode.Castclass:
                    if ((byteCode.Arguments[0].InferredType != null && byteCode.Arguments[0].InferredType.IsGenericParameter) || ((Cecil.TypeReference)operand).IsGenericParameter)
                        return arg1.CastTo(new PrimitiveType("object")).CastTo(operandAsTypeRef);
                    else
                        return arg1.CastTo(operandAsTypeRef);
                case ILCode.Isinst:
                    return arg1.CastAs(operandAsTypeRef);
                case ILCode.Box:
                    return arg1;
                case ILCode.Unbox:
                    return MakeRef(arg1.CastTo(operandAsTypeRef));
                    #endregion
                    #region Indirect
                case ILCode.Ldind_Ref:
                case ILCode.Ldobj:
                    if (arg1 is DirectionExpression)
                        return ((DirectionExpression)arg1).Expression.Detach();
                    else
                        return new UnaryOperatorExpression(UnaryOperatorType.Dereference, arg1);
                case ILCode.Stind_Ref:
                case ILCode.Stobj:
                    if (arg1 is DirectionExpression)
                        return new AssignmentExpression(((DirectionExpression)arg1).Expression.Detach(), arg2);
                    else
                        return new AssignmentExpression(new UnaryOperatorExpression(UnaryOperatorType.Dereference, arg1), arg2);
                    #endregion
                case ILCode.Arglist:
                    return new UndocumentedExpression { UndocumentedExpressionType = UndocumentedExpressionType.ArgListAccess };
                    case ILCode.Break:    return InlineAssembly(byteCode, args);
                case ILCode.Call:
                case ILCode.CallGetter:
                case ILCode.CallSetter:
                    return TransformCall(false, byteCode, args);
                case ILCode.Callvirt:
                case ILCode.CallvirtGetter:
                case ILCode.CallvirtSetter:
                    return TransformCall(true, byteCode,  args);
                    case ILCode.Ldftn: {
                        Cecil.MethodReference cecilMethod = ((MethodReference)operand);
                        var expr = new Ast.IdentifierExpression(cecilMethod.Name);
                        expr.TypeArguments.AddRange(ConvertTypeArguments(cecilMethod));
                        expr.AddAnnotation(cecilMethod);
                        return new IdentifierExpression("ldftn").Invoke(expr)
                            .WithAnnotation(new Transforms.DelegateConstruction.Annotation(false));
                    }
                    case ILCode.Ldvirtftn: {
                        Cecil.MethodReference cecilMethod = ((MethodReference)operand);
                        var expr = new Ast.IdentifierExpression(cecilMethod.Name);
                        expr.TypeArguments.AddRange(ConvertTypeArguments(cecilMethod));
                        expr.AddAnnotation(cecilMethod);
                        return new IdentifierExpression("ldvirtftn").Invoke(expr)
                            .WithAnnotation(new Transforms.DelegateConstruction.Annotation(true));
                    }
                    case ILCode.Calli:       return InlineAssembly(byteCode, args);
                    case ILCode.Ckfinite:    return InlineAssembly(byteCode, args);
                    case ILCode.Constrained: return InlineAssembly(byteCode, args);
                    case ILCode.Cpblk:       return InlineAssembly(byteCode, args);
                    case ILCode.Cpobj:       return InlineAssembly(byteCode, args);
                    case ILCode.Dup:         return arg1;
                    case ILCode.Endfilter:   return InlineAssembly(byteCode, args);
                    case ILCode.Endfinally:  return null;
                    case ILCode.Initblk:     return InlineAssembly(byteCode, args);
                    case ILCode.Initobj:      return InlineAssembly(byteCode, args);
                case ILCode.DefaultValue:
                    return MakeDefaultValue((TypeReference)operand);
                    case ILCode.Jmp: return InlineAssembly(byteCode, args);
                case ILCode.Ldc_I4:
                    return AstBuilder.MakePrimitive((int)operand, byteCode.InferredType);
                case ILCode.Ldc_I8:
                    return AstBuilder.MakePrimitive((long)operand, byteCode.InferredType);
                case ILCode.Ldc_R4:
                case ILCode.Ldc_R8:
                case ILCode.Ldc_Decimal:
                    return new Ast.PrimitiveExpression(operand);
                case ILCode.Ldfld:
                    if (arg1 is DirectionExpression)
                        arg1 = ((DirectionExpression)arg1).Expression.Detach();
                    return arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand);
                case ILCode.Ldsfld:
                    return AstBuilder.ConvertType(((FieldReference)operand).DeclaringType)
                        .Member(((FieldReference)operand).Name).WithAnnotation(operand);
                case ILCode.Stfld:
                    if (arg1 is DirectionExpression)
                        arg1 = ((DirectionExpression)arg1).Expression.Detach();
                    return new AssignmentExpression(arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand), arg2);
                case ILCode.Stsfld:
                    return new AssignmentExpression(
                        AstBuilder.ConvertType(((FieldReference)operand).DeclaringType)
                        .Member(((FieldReference)operand).Name).WithAnnotation(operand),
                        arg1);
                case ILCode.Ldflda:
                    if (arg1 is DirectionExpression)
                        arg1 = ((DirectionExpression)arg1).Expression.Detach();
                    return MakeRef(arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand));
                case ILCode.Ldsflda:
                    return MakeRef(
                        AstBuilder.ConvertType(((FieldReference)operand).DeclaringType)
                        .Member(((FieldReference)operand).Name).WithAnnotation(operand));
                    case ILCode.Ldloc: {
                        ILVariable v = (ILVariable)operand;
                        if (!v.IsParameter)
                            localVariablesToDefine.Add((ILVariable)operand);
                        Expression expr;
                        if (v.IsParameter && v.OriginalParameter.Index < 0)
                            expr = new ThisReferenceExpression();
                        else
                            expr = new Ast.IdentifierExpression(((ILVariable)operand).Name).WithAnnotation(operand);
                        return v.IsParameter && v.Type is ByReferenceType ? MakeRef(expr) : expr;
                    }
                    case ILCode.Ldloca: {
                        ILVariable v = (ILVariable)operand;
                        if (v.IsParameter && v.OriginalParameter.Index < 0)
                            return MakeRef(new ThisReferenceExpression());
                        if (!v.IsParameter)
                            localVariablesToDefine.Add((ILVariable)operand);
                        return MakeRef(new Ast.IdentifierExpression(((ILVariable)operand).Name).WithAnnotation(operand));
                    }
                    case ILCode.Ldnull: return new Ast.NullReferenceExpression();
                    case ILCode.Ldstr:  return new Ast.PrimitiveExpression(operand);
                case ILCode.Ldtoken:
                    if (operand is Cecil.TypeReference) {
                        return AstBuilder.CreateTypeOfExpression((TypeReference)operand).Member("TypeHandle");
                    } else {
                        Expression referencedEntity;
                        string loadName;
                        string handleName;
                        if (operand is Cecil.FieldReference) {
                            loadName = "fieldof";
                            handleName = "FieldHandle";
                            FieldReference fr = (FieldReference)operand;
                            referencedEntity = AstBuilder.ConvertType(fr.DeclaringType).Member(fr.Name).WithAnnotation(fr);
                        } else if (operand is Cecil.MethodReference) {
                            loadName = "methodof";
                            handleName = "MethodHandle";
                            MethodReference mr = (MethodReference)operand;
                            var methodParameters = mr.Parameters.Select(p => new TypeReferenceExpression(AstBuilder.ConvertType(p.ParameterType)));
                            referencedEntity = AstBuilder.ConvertType(mr.DeclaringType).Invoke(mr.Name, methodParameters).WithAnnotation(mr);
                        } else {
                            loadName = "ldtoken";
                            handleName = "Handle";
                            referencedEntity = new IdentifierExpression(FormatByteCodeOperand(byteCode.Operand));
                        }
                        return new IdentifierExpression(loadName).Invoke(referencedEntity).WithAnnotation(new LdTokenAnnotation()).Member(handleName);
                    }
                    case ILCode.Leave:    return new GotoStatement() { Label = ((ILLabel)operand).Name };
                case ILCode.Localloc:
                    {
                        PointerType ptrType = byteCode.InferredType as PointerType;
                        TypeReference type;
                        if (ptrType != null) {
                            type = ptrType.ElementType;
                        } else {
                            type = typeSystem.Byte;
                        }
                        return new StackAllocExpression {
                            Type = AstBuilder.ConvertType(type),
                            CountExpression = DivideBySize(arg1, type)
                        };
                    }
                case ILCode.Mkrefany:
                    {
                        DirectionExpression dir = arg1 as DirectionExpression;
                        if (dir != null) {
                            return new UndocumentedExpression {
                                UndocumentedExpressionType = UndocumentedExpressionType.MakeRef,
                                Arguments = { dir.Expression.Detach() }
                            };
                        } else {
                            return InlineAssembly(byteCode, args);
                        }
                    }
                case ILCode.Refanytype:
                    return new UndocumentedExpression {
                        UndocumentedExpressionType = UndocumentedExpressionType.RefType,
                        Arguments = { arg1 }
                    }.Member("TypeHandle");
                case ILCode.Refanyval:
                    return MakeRef(
                        new UndocumentedExpression {
                            UndocumentedExpressionType = UndocumentedExpressionType.RefValue,
                            Arguments = { arg1, new TypeReferenceExpression(operandAsTypeRef) }
                        });
                    case ILCode.Newobj: {
                        Cecil.TypeReference declaringType = ((MethodReference)operand).DeclaringType;
                        if (declaringType is ArrayType) {
                            ComposedType ct = AstBuilder.ConvertType((ArrayType)declaringType) as ComposedType;
                            if (ct != null && ct.ArraySpecifiers.Count >= 1) {
                                var ace = new Ast.ArrayCreateExpression();
                                ct.ArraySpecifiers.First().Remove();
                                ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers);
                                ace.Type = ct;
                                ace.Arguments.AddRange(args);
                                return ace;
                            }
                        }
                        if (declaringType.IsAnonymousType()) {
                            MethodDefinition ctor = ((MethodReference)operand).Resolve();
                            if (methodDef != null) {
                                AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression();
                                if (CanInferAnonymousTypePropertyNamesFromArguments(args, ctor.Parameters)) {
                                    atce.Initializers.AddRange(args);
                                } else {
                                    for (int i = 0; i < args.Count; i++) {
                                        atce.Initializers.Add(
                                            new NamedExpression {
                                                Name = ctor.Parameters[i].Name,
                                                Expression = args[i]
                                            });
                                    }
                                }
                                return atce;
                            }
                        }
                        var oce = new Ast.ObjectCreateExpression();
                        oce.Type = AstBuilder.ConvertType(declaringType);
                        oce.Arguments.AddRange(args);
                        return oce.WithAnnotation(operand);
                    }
                    case ILCode.No: return InlineAssembly(byteCode, args);
                    case ILCode.Nop: return null;
                    case ILCode.Pop: return arg1;
                    case ILCode.Readonly: return InlineAssembly(byteCode, args);
                case ILCode.Ret:
                    if (methodDef.ReturnType.FullName != "System.Void") {
                        return new Ast.ReturnStatement { Expression = arg1 };
                    } else {
                        return new Ast.ReturnStatement();
                    }
                    case ILCode.Rethrow: return new Ast.ThrowStatement();
                    case ILCode.Sizeof:  return new Ast.SizeOfExpression { Type = operandAsTypeRef };
                    case ILCode.Stloc: {
                        ILVariable locVar = (ILVariable)operand;
                        if (!locVar.IsParameter)
                            localVariablesToDefine.Add(locVar);
                        return new Ast.AssignmentExpression(new Ast.IdentifierExpression(locVar.Name).WithAnnotation(locVar), arg1);
                    }
                    case ILCode.Switch: return InlineAssembly(byteCode, args);
                    case ILCode.Tail: return InlineAssembly(byteCode, args);
                    case ILCode.Throw: return new Ast.ThrowStatement { Expression = arg1 };
                    case ILCode.Unaligned: return InlineAssembly(byteCode, args);
                    case ILCode.Volatile: return InlineAssembly(byteCode, args);
                case ILCode.YieldBreak:
                    return new Ast.YieldBreakStatement();
                case ILCode.YieldReturn:
                    return new Ast.YieldReturnStatement { Expression = arg1 };
                case ILCode.InitObject:
                case ILCode.InitCollection:
                    {
                        ArrayInitializerExpression initializer = new ArrayInitializerExpression();
                        for (int i = 1; i < args.Count; i++) {
                            Match m = objectInitializerPattern.Match(args[i]);
                            if (m.Success) {
                                MemberReferenceExpression mre = m.Get<MemberReferenceExpression>("left").Single();
                                initializer.Elements.Add(
                                    new NamedExpression {
                                        Name = mre.MemberName,
                                        Expression = m.Get<Expression>("right").Single().Detach()
                                    }.CopyAnnotationsFrom(mre));
                            } else {
                                m = collectionInitializerPattern.Match(args[i]);
                                if (m.Success) {
                                    if (m.Get("arg").Count() == 1) {
                                        initializer.Elements.Add(m.Get<Expression>("arg").Single().Detach());
                                    } else {
                                        ArrayInitializerExpression argList = new ArrayInitializerExpression();
                                        foreach (var expr in m.Get<Expression>("arg")) {
                                            argList.Elements.Add(expr.Detach());
                                        }
                                        initializer.Elements.Add(argList);
                                    }
                                } else {
                                    initializer.Elements.Add(args[i]);
                                }
                            }
                        }
                        ObjectCreateExpression oce = arg1 as ObjectCreateExpression;
                        DefaultValueExpression dve = arg1 as DefaultValueExpression;
                        if (oce != null) {
                            oce.Initializer = initializer;
                            return oce;
                        } else if (dve != null) {
                            oce = new ObjectCreateExpression(dve.Type.Detach());
                            oce.CopyAnnotationsFrom(dve);
                            oce.Initializer = initializer;
                            return oce;
                        } else {
                            return new AssignmentExpression(arg1, initializer);
                        }
                    }
                case ILCode.InitializedObject:
                    return new InitializedObjectExpression();
                case ILCode.Wrap:
                    return arg1.WithAnnotation(PushNegation.LiftedOperatorAnnotation);
                case ILCode.AddressOf:
                    return MakeRef(arg1);
                case ILCode.ExpressionTreeParameterDeclarations:
                    args[args.Count - 1].AddAnnotation(new ParameterDeclarationAnnotation(byteCode));
                    return args[args.Count - 1];
                case ILCode.Await:
                    return new UnaryOperatorExpression(UnaryOperatorType.Await, UnpackDirectionExpression(arg1));
                case ILCode.NullableOf:
                case ILCode.ValueOf:
                    return arg1;
                default:
                    throw new Exception("Unknown OpCode: " + byteCode.Code);
            }
        }
Example #6
0
        /// <summary>
        /// Gets the row number in the C# 4.0 spec operator precedence table.
        /// </summary>
        static int GetPrecedence(Expression expr)
        {
            // Note: the operator precedence table on MSDN is incorrect
            if (expr is QueryExpression)
            {
                // Not part of the table in the C# spec, but we need to ensure that queries within
                // primary expressions get parenthesized.
                return(QueryOrLambda);
            }
            UnaryOperatorExpression uoe = expr as UnaryOperatorExpression;

            if (uoe != null)
            {
                if (uoe.Operator == UnaryOperatorType.PostDecrement || uoe.Operator == UnaryOperatorType.PostIncrement)
                {
                    return(Primary);
                }
                else
                {
                    return(Unary);
                }
            }
            if (expr is CastExpression)
            {
                return(Unary);
            }
            BinaryOperatorExpression boe = expr as BinaryOperatorExpression;

            if (boe != null)
            {
                switch (boe.Operator)
                {
                case BinaryOperatorType.Multiply:
                case BinaryOperatorType.Divide:
                case BinaryOperatorType.Modulus:
                    return(13);                            // multiplicative

                case BinaryOperatorType.Add:
                case BinaryOperatorType.Subtract:
                    return(12);                            // additive

                case BinaryOperatorType.ShiftLeft:
                case BinaryOperatorType.ShiftRight:
                    return(11);

                case BinaryOperatorType.GreaterThan:
                case BinaryOperatorType.GreaterThanOrEqual:
                case BinaryOperatorType.LessThan:
                case BinaryOperatorType.LessThanOrEqual:
                    return(RelationalAndTypeTesting);

                case BinaryOperatorType.Equality:
                case BinaryOperatorType.InEquality:
                    return(Equality);

                case BinaryOperatorType.BitwiseAnd:
                    return(8);

                case BinaryOperatorType.ExclusiveOr:
                    return(7);

                case BinaryOperatorType.BitwiseOr:
                    return(6);

                case BinaryOperatorType.ConditionalAnd:
                    return(5);

                case BinaryOperatorType.ConditionalOr:
                    return(4);

                case BinaryOperatorType.NullCoalescing:
                    return(3);

                default:
                    throw new NotSupportedException("Invalid value for BinaryOperatorType");
                }
            }
            if (expr is IsExpression || expr is AsExpression)
            {
                return(RelationalAndTypeTesting);
            }
            if (expr is ConditionalExpression)
            {
                return(Conditional);
            }
            if (expr is AssignmentExpression || expr is LambdaExpression)
            {
                return(Assignment);
            }
            // anything else: primary expression
            return(Primary);
        }
        public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression)
        {
            bool forceSpaces = false;

            switch (binaryOperatorExpression.Operator)
            {
            case BinaryOperatorType.Equality:
            case BinaryOperatorType.InEquality:
                forceSpaces = policy.SpaceAroundEqualityOperator;
                break;

            case BinaryOperatorType.GreaterThan:
            case BinaryOperatorType.GreaterThanOrEqual:
            case BinaryOperatorType.LessThan:
            case BinaryOperatorType.LessThanOrEqual:
                forceSpaces = policy.SpaceAroundRelationalOperator;
                break;

            case BinaryOperatorType.ConditionalAnd:
            case BinaryOperatorType.ConditionalOr:
                forceSpaces = policy.SpaceAroundLogicalOperator;
                break;

            case BinaryOperatorType.BitwiseAnd:
            case BinaryOperatorType.BitwiseOr:
            case BinaryOperatorType.ExclusiveOr:
                forceSpaces = policy.SpaceAroundBitwiseOperator;
                break;

            case BinaryOperatorType.Add:
            case BinaryOperatorType.Subtract:
                forceSpaces = policy.SpaceAroundAdditiveOperator;
                break;

            case BinaryOperatorType.Multiply:
            case BinaryOperatorType.Divide:
            case BinaryOperatorType.Modulus:
                forceSpaces = policy.SpaceAroundMultiplicativeOperator;
                break;

            case BinaryOperatorType.ShiftLeft:
            case BinaryOperatorType.ShiftRight:
                forceSpaces = policy.SpaceAroundShiftOperator;
                break;

            case BinaryOperatorType.NullCoalescing:
                forceSpaces = policy.SpaceAroundNullCoalescingOperator;
                break;
            }
            var opToken = binaryOperatorExpression.OperatorToken;

            if (opToken.PrevSibling != null && opToken.PrevSibling.Role != Roles.NewLine)
            {
                ForceSpacesBefore(opToken, forceSpaces);
            }
            else
            {
                ForceSpacesAfter(binaryOperatorExpression.Left, false);
                FixIndentation(opToken);
            }
            ForceSpacesAfter(opToken, opToken.NextSibling != null && opToken.NextSibling.Role != Roles.NewLine && forceSpaces);

            binaryOperatorExpression.Left.AcceptVisitor(this);
            // Handle line breaks in binary opeartor expression.
            if (binaryOperatorExpression.Left.EndLocation.Line != binaryOperatorExpression.Right.StartLocation.Line)
            {
                if (opToken.StartLocation.Line == binaryOperatorExpression.Right.StartLocation.Line)
                {
                    FixStatementIndentation(opToken.StartLocation);
                }
                else
                {
                    FixStatementIndentation(binaryOperatorExpression.Right.StartLocation);
                }
            }
            binaryOperatorExpression.Right.AcceptVisitor(this);
        }
Example #8
0
 public virtual S VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, T data)
 {
     return(VisitChildren(binaryOperatorExpression, data));
 }
Example #9
0
 void IAstVisitor.VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression)
 {
     Visit(EnterBinaryOperatorExpression, LeaveBinaryOperatorExpression, binaryOperatorExpression);
 }
 public virtual S VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, T data)
 {
     throw new NotImplementedException();
 }
Example #11
0
 public override AstExpression VisitBinaryOperatorExpression(NRefactory.BinaryOperatorExpression binaryOperatorExpression, IScope scope)
 {
     return(AstExpression.Binary(binaryOperatorExpression, scope, this));
 }