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); } }
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); } }
/// <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); }
public virtual S VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, T data) { return(VisitChildren(binaryOperatorExpression, data)); }
void IAstVisitor.VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) { Visit(EnterBinaryOperatorExpression, LeaveBinaryOperatorExpression, binaryOperatorExpression); }
public virtual S VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, T data) { throw new NotImplementedException(); }
public override AstExpression VisitBinaryOperatorExpression(NRefactory.BinaryOperatorExpression binaryOperatorExpression, IScope scope) { return(AstExpression.Binary(binaryOperatorExpression, scope, this)); }