Inheritance: Telerik.JustDecompiler.Ast.Expressions.Expression
        private List<Expression> GetDominatedExpressions(BinaryExpression assignment, IList<Expression> blockExpressions)
        {
            int assignmentIndex = blockExpressions.IndexOf(assignment);
            Expression assignedValue = assignment.Right;
            List<Expression> result = new List<Expression>();
            //ExpressionTreeVisitor etv = new ExpressionTreeVisitor();
            //IEnumerable<VariableReference> variablesUsed = etv.GetUsedVariables(assignedValue);
            //ICollection<ParameterReference> argumentsUsed = etv.GetUsedArguments(assignedValue);

            /// If this is some form of autoassignment
            if (ChangesAssignedExpression(assignment.Right, assignment.Left, assignment.Left))
            {
                return result;
            }

            for (int i = assignmentIndex + 1; i < blockExpressions.Count; i++)
            {
                //TODO: Add breaks and checks
                Expression currentExpression = blockExpressions[i];
                if (ChangesAssignedExpression(currentExpression, assignedValue, assignment.Left))
                {
                    break;
                }
                result.Add(blockExpressions[i]);
            }
            return result;
        }
        private void ProcessBinaryExpression(BinaryExpression binaryExpression)
        {
            if (!binaryExpression.IsAssignmentExpression)
            {
                return;
            }

            if (binaryExpression.Left.CodeNodeType != CodeNodeType.VariableReferenceExpression)
            {
                return;
            }

            CodeNodeType rightCodeNodeType;
            if (binaryExpression.Right.IsArgumentReferenceToRefParameter())
            {
                rightCodeNodeType = CodeNodeType.ArgumentReferenceExpression;
            }
            else
            {
                rightCodeNodeType = binaryExpression.Right.CodeNodeType;
            }

            VariableReference variableReference = (binaryExpression.Left as VariableReferenceExpression).Variable;
            if (this.variableToAssignedCodeNodeTypeMap.ContainsKey(variableReference))
            {
                this.variableToAssignedCodeNodeTypeMap[variableReference] = rightCodeNodeType;
            }
            else
            {
                this.variableToAssignedCodeNodeTypeMap.Add(variableReference, rightCodeNodeType);
            }
        }
        public override ICodeNode VisitBinaryExpression(BinaryExpression node)
        {
            if (node.Operator == BinaryOperator.Assign)
            {
                if (node.Left.CodeNodeType == CodeNodeType.VariableReferenceExpression &&
                    asyncData.AwaiterVariables.Contains((node.Left as VariableReferenceExpression).Variable))
                {
                    VariableReference awaiterVariable = (node.Left as VariableReferenceExpression).Variable;

                    if (node.Right.CodeNodeType == CodeNodeType.MethodInvocationExpression &&
                        (node.Right as MethodInvocationExpression).MethodExpression.Method.Name == "GetAwaiter")
                    {
                        Expression expression = null;//(Expression)Visit((node.Right as MethodInvocationExpression).MethodExpression.Target);
                        MethodInvocationExpression methodInvocation = node.Right as MethodInvocationExpression;
                        if (methodInvocation.MethodExpression.Target != null)
                        {
                            if(methodInvocation.Arguments.Count == 0)
                            {
                                expression = (Expression)Visit(methodInvocation.MethodExpression.Target);
                            }
                        }
                        else
                        {
                            if (methodInvocation.Arguments.Count == 1)
                            {
                                expression = (Expression)Visit(methodInvocation.Arguments[0]);
                            }
                        }

                        if (expression != null && matcherState == MatcherState.FindAwaitExpression)
                        {
                            currentAwaiterVariable = awaiterVariable;
                            awaitedExpression = expression;
                            matcherState = MatcherState.FindIsCompletedInvoke;
                            return null;
                        }
                    }
                    else if ( (node.Right.CodeNodeType == CodeNodeType.ObjectCreationExpression) ||
                        ((node.Right.CodeNodeType == CodeNodeType.LiteralExpression) && ((node.Right as LiteralExpression).Value == null)) )
                    {
                        if ((matcherState & MatcherState.FindInitObj) == MatcherState.FindInitObj &&
                            currentAwaiterVariable == awaiterVariable)
                        {
                            matcherState ^= MatcherState.FindInitObj;
                            return null;
                        }
                    }

                    matcherState = MatcherState.Stopped;
                    return node;
                }
                else if (node.Left.CodeNodeType == CodeNodeType.FieldReferenceExpression &&
                    (node.Left as FieldReferenceExpression).Field.Resolve() == asyncData.StateField ||
                    node.Right.CodeNodeType == CodeNodeType.ThisReferenceExpression)
                {
                    return null;
                }
            }
            return base.VisitBinaryExpression(node);
        }
 public override void VisitBinaryExpression(BinaryExpression node)
 {
     if (!node.IsAssignmentExpression || !CheckForAssignment(node))
     {
         base.VisitBinaryExpression(node);
     }
 }
		public override void VisitBinaryExpression(BinaryExpression node)
		{
			base.VisitBinaryExpression(node);

			if (node.Operator == BinaryOperator.Assign && node.Right.CodeNodeType == CodeNodeType.ArrayCreationExpression)
			{
				ArrayCreationExpression arrayCreation = node.Right as ArrayCreationExpression;
				bool isInitializerPresent = Utilities.IsInitializerPresent(arrayCreation.Initializer);

				if (node.Left.CodeNodeType == CodeNodeType.VariableDeclarationExpression)
				{
					VariableDeclarationExpression variableDeclaration = node.Left as VariableDeclarationExpression;
					node.Left = new ArrayVariableDeclarationExpression(variableDeclaration, arrayCreation.ElementType, 
						arrayCreation.Dimensions.CloneExpressionsOnly(), isInitializerPresent, null);
				}

				if (node.Left.CodeNodeType == CodeNodeType.VariableReferenceExpression)
				{
					VariableReferenceExpression variableReference = node.Left as VariableReferenceExpression;
					node.Left = new ArrayVariableReferenceExpression(variableReference, arrayCreation.ElementType,
						arrayCreation.Dimensions.CloneExpressionsOnly(), isInitializerPresent, null);
				}

				if (node.Left.CodeNodeType == CodeNodeType.FieldReferenceExpression)
				{
					FieldReferenceExpression fieldReference = node.Left as FieldReferenceExpression;
					node.Left = new ArrayAssignmentFieldReferenceExpression(fieldReference, arrayCreation.ElementType,
						arrayCreation.Dimensions.CloneExpressionsOnly(), isInitializerPresent, null);
				}
			}
		}
 public override ICodeNode VisitBinaryExpression(BinaryExpression node)
 {
     if (node.IsAssignmentExpression)
     {
         return VisitAssignExpression(node);
     }
     return base.VisitBinaryExpression(node);
 }
 public override ICodeNode VisitBinaryExpression(BinaryExpression node)
 {
     if (TryTransform(node))
     {
         return node;
     }
     
     return base.VisitBinaryExpression(node);
 }
Exemplo n.º 8
0
        public static Expression Negate(Expression expression, TypeSystem typeSystem)
        {
			if (expression == null)
			{
				return null;
			}

            switch (expression.CodeNodeType)
            {
                case CodeNodeType.BinaryExpression:
                    {
						BinaryExpression binaryExpression = (BinaryExpression)expression;
						if (IsMathOperator(binaryExpression.Operator))
                        {
                            if (binaryExpression.ExpressionType.FullName == "System.Boolean")
                            {
                                return new UnaryExpression(UnaryOperator.LogicalNot, expression, null);
                            }
                            BinaryExpression result =
                                new BinaryExpression(BinaryOperator.ValueEquality, expression, new LiteralExpression(0, typeSystem, null), typeSystem, null);
                            return result;
                        }
                        return NegateBinaryExpression(expression, typeSystem);
                    }
                case CodeNodeType.UnaryExpression:
                    {
                        return NegateUnaryExpression(expression, typeSystem);
                    }
                case CodeNodeType.ConditionExpression:
                    {
                        return NegateConditionExpression(expression, typeSystem);
                    }
            }

            if (expression.CodeNodeType == CodeNodeType.LiteralExpression && expression.ExpressionType.FullName == typeSystem.Boolean.FullName)
            {
                return new LiteralExpression(!(bool)(expression as LiteralExpression).Value, typeSystem, expression.UnderlyingSameMethodInstructions);
            }

            LiteralExpression literalExpression = expression.ExpressionType.GetDefaultValueExpression(typeSystem) as LiteralExpression;
			if (literalExpression != null)
            {
				if (literalExpression.ExpressionType.FullName == typeSystem.Boolean.FullName)
				{
					UnaryExpression unaryResult = new UnaryExpression(UnaryOperator.LogicalNot, expression, null);
					return unaryResult;
				}
                BinaryExpression result = new BinaryExpression(BinaryOperator.ValueEquality, expression, literalExpression, typeSystem, null);
                return result;
            }
            else
            {
                return new UnaryExpression(UnaryOperator.LogicalNot, expression, null);
            }
        }
		protected bool IsAssignToVariableExpression(BinaryExpression theAssignExpression, out VariableReference theVariable)
		{
			theVariable = null;
			bool result = theAssignExpression != null && theAssignExpression.IsAssignmentExpression &&
					 (theAssignExpression.Left.CodeNodeType == CodeNodeType.VariableReferenceExpression ||
					  theAssignExpression.Left.CodeNodeType == CodeNodeType.VariableDeclarationExpression);
			if (result)
			{
				theVariable = GetVariableReferenceFromExpression(theAssignExpression.Left);
			}
			return result;
		}
 public override ICodeNode VisitBinaryExpression(BinaryExpression node)
 {
     if (node.IsAssignmentExpression)
     {
         if (node.Left.CodeNodeType == CodeNodeType.VariableReferenceExpression)
         {
             node.Right = (Expression)Visit(node.Right);
             return node;
         }
     }
     return base.VisitBinaryExpression(node);
 }
		//x = cond ? y : z;
		//
		//==
		//
		//if(cond)
		//{
		//      x = y;
		//}
		//else
		//{
		//      x = z;
		//}
		//
		//x - phi variable
		//y, z - expressions

		public bool TryMatchInternal(IfStatement theIfStatement, out Statement result)
		{
			result = null;

			if (theIfStatement == null)
			{
				return false;
			}

			VariableReference xVariableReference = null;
			VariableReference x1VariableReference = null;
			Expression yExpressionValue;
			Expression zExpressionValue;

			if (theIfStatement.Else == null ||
				theIfStatement.Then.Statements.Count != 1 || theIfStatement.Else.Statements.Count != 1 ||
				theIfStatement.Then.Statements[0].CodeNodeType != CodeNodeType.ExpressionStatement ||
				theIfStatement.Else.Statements[0].CodeNodeType != CodeNodeType.ExpressionStatement)
			{
				return false;
			}

			BinaryExpression thenAssignExpression = (theIfStatement.Then.Statements[0] as ExpressionStatement).Expression as BinaryExpression;
			BinaryExpression elseAssignExpression = (theIfStatement.Else.Statements[0] as ExpressionStatement).Expression as BinaryExpression;
			if (!IsAssignToVariableExpression(thenAssignExpression, out x1VariableReference) || 
				!IsAssignToVariableExpression(elseAssignExpression, out xVariableReference))
			{
				return false;
			}

			if (xVariableReference != x1VariableReference)
			{
				return false;
			}
			if (!ShouldInlineExpressions(thenAssignExpression, elseAssignExpression))
			{
				/// Although correct syntax, nesting ternary expressions makes the code very unreadable.
				return false;
			}

			yExpressionValue = GetRightExpressionMapped(thenAssignExpression);
            zExpressionValue = GetRightExpressionMapped(elseAssignExpression);

			ConditionExpression ternaryConditionExpression = new ConditionExpression(theIfStatement.Condition, yExpressionValue, zExpressionValue, null);
			BinaryExpression ternaryAssign = new BinaryExpression(BinaryOperator.Assign,
				new VariableReferenceExpression(xVariableReference, null), ternaryConditionExpression, this.typeSystem, null);

            result = new ExpressionStatement(ternaryAssign) { Parent = theIfStatement.Parent };
            FixContext(xVariableReference.Resolve(), 1, 0, result as ExpressionStatement);
			return true;
		}
        private void InsertTopLevelParameterAssignments(BlockStatement block)
        {
            for (int i = 0; i < this.context.MethodContext.OutParametersToAssign.Count; i++)
            {
                ParameterDefinition parameter = this.context.MethodContext.OutParametersToAssign[i];
                TypeReference nonPointerType = parameter.ParameterType.IsByReference ? parameter.ParameterType.GetElementType() : parameter.ParameterType;
                UnaryExpression parameterDereference =
                    new UnaryExpression(UnaryOperator.AddressDereference, new ArgumentReferenceExpression(parameter, null), null);

                BinaryExpression assignExpression = new BinaryExpression(BinaryOperator.Assign, parameterDereference,
                    nonPointerType.GetDefaultValueExpression(typeSystem), nonPointerType, typeSystem, null);

                block.AddStatementAt(i, new ExpressionStatement(assignExpression));
            }
        }
		public override void VisitBinaryExpression(BinaryExpression node)
		{
			base.VisitBinaryExpression(node);
			if (node.IsAssignmentExpression && node.Right.CodeNodeType == CodeNodeType.DelegateCreationExpression)
			{
				DelegateCreationExpression theDelegateCreation = (DelegateCreationExpression)node.Right;
				if (node.Left.HasType)
				{
					TypeReference leftType = node.Left.ExpressionType;
					if (CanInferTypeOfDelegateCreation(leftType)) 
					{
						theDelegateCreation.TypeIsImplicitlyInferable = true;
					}
				}
			}
		}
        public override ICodeNode VisitBinaryExpression(BinaryExpression node)
        {
            if (node.IsAssignmentExpression)
            {
                return VisitAssignExpression(node);
            }

            ICodeNode newNode = canCastStep.VisitBinaryExpression(node);
            if (newNode != null)
                return newNode;

            if (node.Operator == BinaryOperator.ValueEquality || node.Operator == BinaryOperator.ValueInequality)
            {
                return VisitCeqExpression(node);
            }

            return base.VisitBinaryExpression(node);
        }
        public override ICodeNode VisitBinaryExpression(BinaryExpression node)
        {
            if (node.IsAssignmentExpression)
            {
                if (node.Left.CodeNodeType == CodeNodeType.FieldReferenceExpression)
                {
                    FieldDefinition theFieldDef = (node.Left as FieldReferenceExpression).Field.Resolve();
                    if (theFieldDef != null && fieldsToRemove.ContainsKey(theFieldDef))
                    {
                        throw new Exception("A caching field cannot be assigned more than once.");
                    }
                }
                else if (node.Left.CodeNodeType == CodeNodeType.VariableReferenceExpression)
                {
                    if (variablesToRemove.ContainsKey((node.Left as VariableReferenceExpression).Variable))
                    {
                        throw new Exception("A caching variable cannot be assigned more than once.");
                    }
                }
            }

            return base.VisitBinaryExpression(node);
        }
Exemplo n.º 16
0
        public override void VisitBinaryExpression(BinaryExpression node)
        {
            if (!node.IsAssignmentExpression)
            {
                base.VisitBinaryExpression(node);
                return;
            }

            Visit(node.Right);
            if (this.searchResult != UsageFinderSearchResult.NotFound)
            {
                return;
            }

            if (CheckExpression(node.Left))
            {
                this.searchResult = UsageFinderSearchResult.Assigned;
            }
            else
            {
                base.Visit(node.Left);
            }
        }
 /// <summary>
 /// Adds the starting assignments to the newly introduced flag variables.
 /// </summary>
 /// <param name="body">The body of the method.</param>
 private void AddDefaultAssignmentsToNewConditionalVariables(BlockStatement body)
 {
     foreach (VariableDefinition variable in labelToVariable.Values)
     {
         ///Add assignments for every label variable.
         BinaryExpression defaultAssignment =
             new BinaryExpression(BinaryOperator.Assign, new VariableReferenceExpression(variable, null), GetLiteralExpression(false), typeSystem, null);
         body.AddStatementAt(0, new ExpressionStatement(defaultAssignment));
     }
     if (usedBreakVariable)
     {
         ///Add assignment for the break variable.
         BinaryExpression defaultBreakAssignment =
             new BinaryExpression(BinaryOperator.Assign, new VariableReferenceExpression(breakVariable, null), GetLiteralExpression(false), typeSystem, null);
         body.AddStatementAt(0, new ExpressionStatement(defaultBreakAssignment));
     }
     if (usedContinueVariable)
     {
         ///Add assignment for the continue variable.
         BinaryExpression defaultContinueAssignment =
             new BinaryExpression(BinaryOperator.Assign, new VariableReferenceExpression(continueVariable, null), GetLiteralExpression(false), typeSystem, null);
         body.AddStatementAt(0, new ExpressionStatement(defaultContinueAssignment));
     }
 }
        private bool CheckForAssignment(BinaryExpression node)
        {
            if (node.Left.CodeNodeType == CodeNodeType.ArgumentReferenceExpression &&
                (node.Left as ArgumentReferenceExpression).Parameter.ParameterType.IsByReference)
            {
                throw new Exception("Managed pointer usage not in SSA");
            }

            if (node.Left.CodeNodeType != CodeNodeType.VariableReferenceExpression ||
                !(node.Left as VariableReferenceExpression).Variable.VariableType.IsByReference)
            {
                return false;
            }

            VariableDefinition byRefVariable = (node.Left as VariableReferenceExpression).Variable.Resolve();

            if (variableToAssignExpression.ContainsKey(byRefVariable))
            {
                throw new Exception("Managed pointer usage not in SSA");
            }

            variableToAssignExpression.Add(byRefVariable, node);
            return true;
        }
		private bool TryGetAssignment(StatementCollection statements, int startIndex, out BinaryExpression binaryExpression)
		{
			binaryExpression = null;

			var statement = statements[startIndex];
			if (statement.CodeNodeType != CodeNodeType.ExpressionStatement)
			{
				return false;
			}
			Expression firstExpression = (statement as ExpressionStatement).Expression;

			if (firstExpression.CodeNodeType != CodeNodeType.BinaryExpression)
			{
				return false;
			}
			var result = firstExpression as BinaryExpression;

			if (!result.IsAssignmentExpression)
			{
				return false;
			}

			if (!(result.Left.CodeNodeType == CodeNodeType.VariableReferenceExpression ||
				  result.Left.CodeNodeType == CodeNodeType.VariableDeclarationExpression ||
				  result.Left.CodeNodeType == CodeNodeType.FieldReferenceExpression ||
				  result.Left.CodeNodeType == CodeNodeType.ThisReferenceExpression ||
				  result.Left.CodeNodeType == CodeNodeType.PropertyReferenceExpression ||
				  result.Left.CodeNodeType == CodeNodeType.ArgumentReferenceExpression ||
				  result.Left.CodeNodeType == CodeNodeType.UnaryExpression && (result.Left as UnaryExpression).Operand.CodeNodeType == CodeNodeType.ArgumentReferenceExpression))
			{
				return false;
			}

			binaryExpression = result;
			return true;
		}
 private bool IsForeachVariableAssignment(BinaryExpression assignment)
 {
     if (assignment == null)
     {
         return false;
     }
     Expression getCurrentInvocation;
     if (assignment.Right is CastExpression)
     {
         getCurrentInvocation = (assignment.Right as CastExpression).Expression;
     }
     else if (assignment.Right is MethodInvocationExpression || assignment.Right is PropertyReferenceExpression)
     {
         getCurrentInvocation = assignment.Right;
     }
     else
     {
         return false;
     }
     if (IsGetCurrent(getCurrentInvocation))
     {
         VariableReferenceExpression variable = assignment.Left as VariableReferenceExpression;
         if (variable == null)
         {
             return false;
         }
         foreachVariable = variable.Variable.Resolve();
         foreachVariableInstructions.AddRange(assignment.UnderlyingSameMethodInstructions);
         foreachVariableType = assignment.Right.ExpressionType;
         return true;
     }
     return false;
 }
		public override void VisitBinaryExpression(BinaryExpression node)
		{
			Visit(node.Left);

			WriteSpace();

			bool isOneSideNull = IsNull(node.Left) || IsNull(node.Right);
			string @operator = ToString(node.Operator, isOneSideNull);

			if (this.Language.IsOperatorKeyword(@operator))
			{
				WriteKeyword(@operator);
			}
			else
			{
				Write(@operator);
			}

			if (node.Right.CodeNodeType == CodeNodeType.InitializerExpression)
			{
				StartInitializer(node.Right as InitializerExpression);
			}
			else
			{
				WriteSpace();
			}

			Visit(node.Right);
		}
Exemplo n.º 22
0
        public override ICodeNode VisitBinaryExpression(BinaryExpression node)
        {
            node = (BinaryExpression)base.VisitBinaryExpression(node);

            if (!node.Left.HasType)
            {
                /// Tests, where the left part of the expression is event fail.
                return node;
            }
            TypeDefinition leftType = node.Left.ExpressionType.Resolve();
            if (leftType == null)
            {
                return node;
            }
			if (leftType.IsEnum && !node.Left.ExpressionType.IsArray)
			{
				if (node.Right is LiteralExpression)
				{
					node.Right = EnumHelper.GetEnumExpression(leftType, (node.Right as LiteralExpression), typeSystem);
				}
				else if (node.Right is CastExpression && (node.Right as CastExpression).Expression is LiteralExpression)
				{
					node.Right = EnumHelper.GetEnumExpression(leftType, (node.Right as CastExpression).Expression as LiteralExpression, typeSystem);
				}
			}
			else
			{
				if (!node.Right.HasType)
				{
					// Tests, where the right part of the expression is delegate fail.
					return node;
				}
				TypeDefinition rightType = node.Right.ExpressionType.Resolve();
				if (rightType == null)
				{
					return node;
				}
				if (rightType.IsEnum && !node.Right.ExpressionType.IsArray)
				{
					if (node.Left is LiteralExpression)
					{
						node.Left = EnumHelper.GetEnumExpression(rightType, (node.Left as LiteralExpression), typeSystem);
					}
					else if (node.Left is CastExpression && (node.Left as CastExpression).Expression is LiteralExpression)
					{
						node.Left = EnumHelper.GetEnumExpression(rightType, (node.Left as CastExpression).Expression as LiteralExpression, typeSystem);
					}
				}
			}

            return node;
        }
        /// <summary>
        /// The method for updating BinaryExpression.
        /// </summary>
        /// <param name="expression">The binary expression to be updated.</param>
        /// <returns>Returns the updated binary expression.</returns>
        public override ICodeNode VisitBinaryExpression(BinaryExpression expression)
        {
            ///Update the nested expressions first.
            expression.Left = (Expression)Visit(expression.Left);
            expression.Right = (Expression)Visit(expression.Right);

            TypeReference leftType = expression.Left.ExpressionType;
            leftType = GetElementType(leftType);

            if (leftType != null)
            {
                /// Check for chars.
                if (leftType.FullName == typeSystem.Char.FullName)
                {
                    if (expression.Right.CodeNodeType == CodeNodeType.LiteralExpression)
                    {
                        if (IsArithmeticOperator(expression.Operator))
                        {
                            /// Might need to add cast to char at this point.
                            // return new CastExpression(expression, typeSystem.Char);
                            expression.ExpressionType = typeSystem.Char;
                            return expression;
                        }
                        if (expression.Right.HasType)
                        {
                            TypeReference rightLitType = GetElementType(expression.Right.ExpressionType);
                            if (leftType.FullName == rightLitType.FullName)
                            {
                                return expression;
                            }
                        }
                        LiteralExpression right = expression.Right as LiteralExpression;
                        expression.Right = GetLiteralExpression((char)((int)right.Value), right.MappedInstructions);
                    }
                    TypeReference rightType = GetElementType(expression.Right.ExpressionType);
                    if (rightType.FullName != typeSystem.Char.FullName)
                    {
                        if (expression.Right.CodeNodeType == CodeNodeType.CastExpression && expression.Right.ExpressionType.FullName == typeSystem.UInt16.FullName)
                        {
                            ((CastExpression)expression.Right).TargetType = typeSystem.Char;
                        }
                        else
                        {
                            expression.Right = new CastExpression(expression.Right, typeSystem.Char, null);
                        }
                    }
                }

                /// Check for bools.
                if (leftType.FullName == typeSystem.Boolean.FullName)
                {
                    if (expression.Right.CodeNodeType == CodeNodeType.LiteralExpression)
                    {
                        if (expression.Operator == BinaryOperator.ValueEquality || expression.Operator == BinaryOperator.ValueInequality || IsBooleanAssignmentOperator(expression.Operator))
                        {
                            LiteralExpression right = expression.Right as LiteralExpression;
                            bool newVal = true;
                            if (right.Value == null || right.Value.Equals(0) || right.Value.Equals(false) || right.Value.Equals(null))
                            {
                                newVal = false;
                            }
                            expression.Right = GetLiteralExpression(newVal, right.MappedInstructions);
                        }

                        if (expression.Operator == BinaryOperator.ValueEquality || expression.Operator == BinaryOperator.ValueInequality)
                        {
                            return SimplifyBooleanComparison(expression);
                        }
                    }
                }
            }

            if (expression.Operator == BinaryOperator.ValueEquality || expression.Operator == BinaryOperator.ValueInequality)
            {
                TypeReference rightType = GetElementType(expression.Right.ExpressionType);
                if (rightType != null && leftType != null && rightType.FullName != leftType.FullName)
                {
                    return FixEqualityComparisonExpression(expression);
                }
            }

            ///Adds downcasts in pointer types.
            if (expression.IsAssignmentExpression)
            {
                if (NeedsPointerCast(expression))
                {
                    if (expression.Right.CodeNodeType == CodeNodeType.StackAllocExpression)
                    {
                        expression.Right.ExpressionType = expression.Left.ExpressionType;
                    }
                    else
                    {
                        expression.Right = new CastExpression(expression.Right, expression.Left.ExpressionType, null);
                    }
                }
                else if (expression.Left.HasType)
                {
                    if (expression.Left.ExpressionType.IsByReference || expression.Left.ExpressionType.IsPointer || expression.Left.ExpressionType.IsArray ||
                        !expression.Left.ExpressionType.IsPrimitive)
                    {
                        TypeDefinition leftResolved = expression.Left.ExpressionType.Resolve();
                        if (leftResolved != null && !leftResolved.IsEnum)
                        {
                            if (expression.Right is LiteralExpression)
                            {
                                LiteralExpression rightLit = expression.Right as LiteralExpression;
                                if (rightLit.Value != null && rightLit.Value.Equals(0))
                                {
                                    expression.Right = new LiteralExpression(null, typeSystem, expression.Right.UnderlyingSameMethodInstructions);
                                }
                            }
                        }
                    }
                }
            }

            if (expression.Operator == BinaryOperator.GreaterThan &&
                expression.MappedInstructions.Count() == 1 &&
                expression.MappedInstructions.First().OpCode.Code == Code.Cgt_Un)
            {
                LiteralExpression literal = null;
                if (expression.Right.CodeNodeType == CodeNodeType.LiteralExpression)
                {
                    literal = expression.Right as LiteralExpression;
                }
                else if (expression.Right.CodeNodeType == CodeNodeType.CastExpression)
                {
                    CastExpression cast = expression.Right as CastExpression;
                    if (cast.Expression.CodeNodeType == CodeNodeType.LiteralExpression)
                    {
                        literal = cast.Expression as LiteralExpression;
                    }
                }

                if (literal != null)
                {
                    if (literal.Value == null || literal.Value.Equals(0))
                    {
                        expression.Operator = BinaryOperator.ValueInequality;
                    }
                }
            }

            /// Adds cast to object if needed.
            if (expression.IsObjectComparison)
            {
                Expression left = expression.Left;
                Expression right = expression.Right;
                TypeReference leftUnresolvedReference;
                TypeReference rightUnresolvedReference;
                if (CheckForOverloadedEqualityOperators(expression.Left, out leftUnresolvedReference) &&
                    CheckForOverloadedEqualityOperators(expression.Right, out rightUnresolvedReference))
                {
                    expression.Left = new CastExpression(left, left.ExpressionType.Module.TypeSystem.Object, left.MappedInstructions, leftUnresolvedReference);
                    expression.Right = new CastExpression(right, right.ExpressionType.Module.TypeSystem.Object, right.MappedInstructions, rightUnresolvedReference);

                }
            }

            return expression;
        }
 /// <summary>
 /// Simplifies boolean expressions.
 /// </summary>
 /// <param name="expression">The expression to be simplified.</param>
 /// <returns>Returns the simplified expression.</returns>
 private Expression SimplifyBooleanComparison(BinaryExpression expression)
 {
     bool isFalse = IsFalse(expression.Right);
     if (isFalse && expression.Operator == BinaryOperator.ValueEquality ||
         !isFalse && expression.Operator == BinaryOperator.ValueInequality)
     {
         List<Instruction> instructions = new List<Instruction>(expression.MappedInstructions);
         instructions.AddRange(expression.Right.UnderlyingSameMethodInstructions);
         return Negator.Negate(expression.Left, typeSystem).CloneAndAttachInstructions(instructions);
     }
     return expression;
 }
 private bool NeedsPointerCast(BinaryExpression expression)
 {
     if (!expression.Left.ExpressionType.IsPointer && !expression.Left.ExpressionType.IsByReference)
     {
         return false;
     }
     return expression.Left.ExpressionType.GetElementType().FullName != expression.Right.ExpressionType.GetElementType().FullName;
 }
        /// <summary>
        /// Fixes expressions produced by ceq and beq.
        /// </summary>
        /// <param name="expression">The comparison expression.</param>
        /// <returns>Returns the updated binary expression.</returns>
        private ICodeNode FixEqualityComparisonExpression(BinaryExpression expression)
        {
            /// The generated expression is (ValueOnTopOfStack == 0)
            if (expression.Right is LiteralExpression)
            {
                TypeReference leftType = GetElementType(expression.Left.ExpressionType);
                if (leftType.FullName != typeSystem.Boolean.FullName)
                {
                    /// Left type is not boolean
                    TypeDefinition resolved = leftType.Resolve();
                    /// If the type is not primitive, the check should be against 'null', not against '0'
                    if (leftType != null && !leftType.IsPrimitive && (resolved != null && !resolved.IsEnum))
                    {
                        expression.Right = GetLiteralExpression(null, null);
                    }
                    /// The check against 0 is correct
                    return expression;
                }

                /// At this point the left side of 'expression' is boolean
                LiteralExpression rightLiteral = expression.Right as LiteralExpression;
                if (rightLiteral.Value.Equals(0) || rightLiteral.Value.Equals(null))
                {
                    return new UnaryExpression(UnaryOperator.LogicalNot, expression.Left, null);
                }
                else
                {
                    return expression.Left;
                }
            }
            return expression;
        }
        /// <summary>
        /// Fixes expressions, generated for brtrue and brfalse. As 0,false and null are all represented as 0 in IL, this step adds the correct constant
        /// to the expression.
        /// </summary>
        /// <param name="expression">The expression.</param>
        /// <param name="isBrTrue">The type of jump.</param>
        /// <returns>Returns the fixed expression.</returns>
        private ICodeNode FixBranchingExpression(Expression expression, Instruction branch)
        {
            /// example:
            /// before the step:
            /// ...
            /// a //a is int32, opperation is brfalse
            /// After the step:
            /// ...
            /// a == 0

            bool isBrTrue = branch.OpCode.Code == Code.Brtrue || branch.OpCode.Code == Code.Brtrue_S;

            TypeReference expressionType = expression.ExpressionType;
            BinaryExpression newCondition;
            BinaryOperator operation = BinaryOperator.ValueEquality;
            Instruction[] instructions = new Instruction[] { branch };
            if (isBrTrue)
            {
                operation = BinaryOperator.ValueInequality;
            }
            if (expressionType.Name == "Boolean" || expressionType.Name.Contains("Boolean "))
            {
                Expression operand;
                if (!isBrTrue)
                {
                    operand = Negator.Negate(expression, typeSystem);
                }
                else
                {
                    operand = expression;
                }

                Expression result;
                if (expression is SafeCastExpression)
                {
                    result = new BinaryExpression(operation, expression, GetLiteralExpression(false, null), typeSystem, instructions);
                }
                else
                {
                    result = new UnaryExpression(UnaryOperator.None, operand, instructions);
                }

                return result;
            }
            if (expressionType.Name == "Char")
            {
                newCondition = new BinaryExpression(operation, expression, GetLiteralExpression('\u0000', null), typeSystem, instructions);
                newCondition.ExpressionType = typeSystem.Boolean;
            }
            if (!expressionType.IsPrimitive)
            {
                TypeDefinition expressionTypeDefinition = expressionType.Resolve();

                /// expressionTypeDefinition can resolve to null when dealing with generics
                if (expressionTypeDefinition != null && expressionTypeDefinition.IsEnum && !expressionType.IsArray)
                {
                    ///Find the field that corresponds to 0
                    FieldDefinition field = null;
                    foreach (FieldDefinition enumField in expressionTypeDefinition.Fields)
                    {
                        if (enumField.Constant != null && enumField.Constant.Value != null && enumField.Constant.Value.Equals(0))
                        {
                            field = enumField;
                            break;
                        }
                    }

                    if (field == null)
                    {
                        newCondition = new BinaryExpression(operation, expression, GetLiteralExpression(0, null), typeSystem, instructions);
                        newCondition.ExpressionType = typeSystem.Boolean;
                    }
                    else
                    {
                        newCondition = new BinaryExpression(operation, expression, new EnumExpression(field, null), typeSystem, instructions);
                        newCondition.ExpressionType = typeSystem.Boolean;
                    }
                }
                else
                {
                    /// If it is not primitive class, then the check should be against null
                    newCondition = new BinaryExpression(operation, expression, GetLiteralExpression(null, null), typeSystem, instructions);
                    newCondition.ExpressionType = typeSystem.Boolean;
                }
            }
            else
            {
                /// This is primitive type, the check should be against 0
                newCondition = new BinaryExpression(operation, expression, GetLiteralExpression(0, null), typeSystem, instructions);
                newCondition.ExpressionType = typeSystem.Boolean;
            }
            return newCondition;
        }
        internal BinaryExpression VisitAssignExpression(BinaryExpression node)
        {
            Expression left = node.Left;
            TypeDefinition tr = left.ExpressionType.Resolve();
            if (tr == null)
            {
                return null;
            }
            if (tr.BaseType!= null && tr.BaseType.Name == "MulticastDelegate")
            {
                Expression right = node.Right;
                MethodInvocationExpression methodInvocation = right as MethodInvocationExpression;
                if (right is CastExpression)
                {
                    methodInvocation = (right as CastExpression).Expression as MethodInvocationExpression;
                }
                if (methodInvocation == null)
                {
                    return null;
                }
                if (methodInvocation.Arguments.Count == 2)
                {
                    Expression firstArgument = methodInvocation.Arguments[0];
                    Expression secondArgument = methodInvocation.Arguments[1];
                    BinaryOperator @operator;

                    if (!AreTheSame(firstArgument, left))
                    {
                        return null;
                    }
                    //if firstArgument == leftSide

                    if (methodInvocation.MethodExpression.Method.Name == "Combine")
                    {
                        @operator = BinaryOperator.AddAssign;
                    }
                    else if (methodInvocation.MethodExpression.Method.Name == "Remove")
                    {
                        @operator = BinaryOperator.SubtractAssign;
                    }
                    else
                    {
                        return null;
                    }
                    List<Instruction> instructions = new List<Instruction>(node.MappedInstructions);
                    instructions.AddRange(methodInvocation.InvocationInstructions);
                    return new BinaryExpression(@operator, left, secondArgument, typeSystem, instructions);
                }
            }
            return null;
        }
		ICodeNode BuildBinaryExpression(BinaryOperator @operator, Expression left, Expression right, TypeReference expressionType, IEnumerable<Instruction> instructions)
		{
			BinaryExpression result =
				new BinaryExpression(@operator, (Expression)codeTransformer.Visit(left), (Expression)codeTransformer.Visit(right), 
								expressionType, typeSystem, instructions, true);
			if (result.IsComparisonExpression || result.IsLogicalExpression)
			{
				result.ExpressionType = left.ExpressionType.Module.TypeSystem.Boolean;
			}
			return result;
		}
 public int CompareOperators(BinaryExpression other)
 {
     return this.OperatorPriority.CompareTo(other.OperatorPriority);
 }