Esempio n. 1
0
        public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unary, object data)
        {
            // lifted operators can't be transformed
            if (unary.Annotation <LiftedOperator>() != null || unary.Expression.Annotation <LiftedOperator>() != null)
            {
                return(base.VisitUnaryOperatorExpression(unary, data));
            }

            // Remove double negation
            // !!a
            if (unary.Operator == UnaryOperatorType.Not &&
                unary.Expression is UnaryOperatorExpression &&
                (unary.Expression as UnaryOperatorExpression).Operator == UnaryOperatorType.Not)
            {
                AstNode newNode = (unary.Expression as UnaryOperatorExpression).Expression;
                unary.ReplaceWith(newNode.WithAnnotation(unary.GetAllILRanges()));
                return(newNode.AcceptVisitor(this, data));
            }

            // Push through binary operation
            // !((a) op (b))
            BinaryOperatorExpression binaryOp = unary.Expression as BinaryOperatorExpression;

            if (unary.Operator == UnaryOperatorType.Not && binaryOp != null)
            {
                bool successful = true;
                switch (binaryOp.Operator)
                {
                case BinaryOperatorType.Equality:
                    binaryOp.Operator = BinaryOperatorType.InEquality;
                    break;

                case BinaryOperatorType.InEquality:
                    binaryOp.Operator = BinaryOperatorType.Equality;
                    break;

                case BinaryOperatorType.GreaterThan:                         // TODO: these are invalid for floats (stupid NaN)
                    binaryOp.Operator = BinaryOperatorType.LessThanOrEqual;
                    break;

                case BinaryOperatorType.GreaterThanOrEqual:
                    binaryOp.Operator = BinaryOperatorType.LessThan;
                    break;

                case BinaryOperatorType.LessThanOrEqual:
                    binaryOp.Operator = BinaryOperatorType.GreaterThan;
                    break;

                case BinaryOperatorType.LessThan:
                    binaryOp.Operator = BinaryOperatorType.GreaterThanOrEqual;
                    break;

                default:
                    successful = false;
                    break;
                }
                if (successful)
                {
                    unary.ReplaceWith(binaryOp.WithAnnotation(unary.GetAllILRanges()));
                    return(binaryOp.AcceptVisitor(this, data));
                }

                successful = true;
                switch (binaryOp.Operator)
                {
                case BinaryOperatorType.ConditionalAnd:
                    binaryOp.Operator = BinaryOperatorType.ConditionalOr;
                    break;

                case BinaryOperatorType.ConditionalOr:
                    binaryOp.Operator = BinaryOperatorType.ConditionalAnd;
                    break;

                default:
                    successful = false;
                    break;
                }
                if (successful)
                {
                    binaryOp.Left.ReplaceWith(e => new UnaryOperatorExpression(UnaryOperatorType.Not, e));
                    binaryOp.Right.ReplaceWith(e => new UnaryOperatorExpression(UnaryOperatorType.Not, e));
                    unary.ReplaceWith(binaryOp.WithAnnotation(unary.GetAllILRanges()));
                    return(binaryOp.AcceptVisitor(this, data));
                }
            }
            return(base.VisitUnaryOperatorExpression(unary, data));
        }