예제 #1
0
        internal Expr SimplifyRelop()
        {
            Expr      l   = lchild_();
            Expr      r   = rchild_();
            ConstExpr lce = l is ConstExpr ? (ConstExpr)l : null;
            ConstExpr rce = r is ConstExpr ? (ConstExpr)r : null;

            if (op_ == "is" || op_ == "is not")
            {
                if ((lce == null && rce != null) || (lce != null && rce == null))
                {
                    return(this);
                }

                if (((lce == null && rce == null)) || ((lce != null && lce.IsNull()) && (rce != null && rce.IsNull())))
                {
                    if (op_ == "is" || op_ == "is not")
                    {
                        string val = op_ == "is" ? "true" : "false";
                        return(ConstExpr.MakeConst(val, new BoolType(), outputName_));
                    }
                }

                if (((lce is null && rce is null)) || ((lce != null && !lce.IsNull()) && (rce != null && !rce.IsNull())))
                {
                    if (op_ == "is" || op_ == "is not")
                    {
                        string val = op_ == "is" ? "false" : "true";
                        return(ConstExpr.MakeConst(val, new BoolType(), outputName_));
                    }
                }

                if (lce != null && !lce.IsNull() && rce != null && rce.IsNull())
                {
                    if (op_ == "is" || op_ == "is not")
                    {
                        string val = op_ == "is" ? "false" : "true";
                        return(ConstExpr.MakeConst(val, new BoolType(), outputName_));
                    }
                }

                if (((lce != null && lce.IsNull()) || (rce != null && rce.IsNull())))
                {
                    if (op_ == "is" || op_ == "is not")
                    {
                        string val = op_ == "is" ? "true" : "false";
                        return(ConstExpr.MakeConst(val, new BoolType(), outputName_));
                    }
                }
            }

            if (lce == null && rce == null)
            {
                return(this);
            }

            if (!(lce is null || rce is null))
            {
                if (lce.IsTrue() && rce.IsTrue())
                {
                    return(lce);
                }
                else
                {
                    return(lce.IsTrue() ? lce : rce);
                }
            }
예제 #2
0
        public override Expr Normalize()
        {
            // all children get normalized first
            for (int i = 0; i < children_.Count; ++i)
            {
                Expr x = children_[i];
                children_[i] = x.Normalize();
            }

            Expr      l   = lchild_();
            Expr      r   = rchild_();
            ConstExpr lce = (l is ConstExpr) ? (ConstExpr)l : null;
            ConstExpr rce = (r is ConstExpr) ? (ConstExpr)r : null;

            switch (op_)
            {
            case "+":
            case "-":
            case "*":
            case "/":
            case ">":
            case ">=":
            case "<":
            case "<=":
            case "||":
            case "=":
            case "<>":
            case "!=":
            case " and ":
            case " or ":
            case "is":
            case "is not":
                if ((lce != null && lce.val_ is null) || (rce != null && rce.val_ is null))
                {
                    if (IsRelOp())
                    {
                        // needs to be TRUE or FALSE
                        if ((op_ == "is") || (op_ == "is not") || (lce != null && TypeBase.IsNumberType(l.type_)) || (rce != null && TypeBase.IsNumberType(r.type_)))
                        {
                            return(SimplifyRelop());
                        }
                    }

                    // NULL simplification: if operator is not relational, X op NULL is NULL
                    if (lce != null && lce.val_ is null)
                    {
                        return(lce);
                    }

                    if (rce != null && rce.IsNull())
                    {
                        return(rce);
                    }
                }

                if (lce != null && rce != null)
                {
                    // Simplify Constants: children are not non null constants, evaluate them.
                    Value val = Exec(null, null);
                    return(ConstExpr.MakeConst(val, type_, outputName_));
                }

                if (lce != null && rce == null && isPlainSwappableConstOp())
                {
                    SwapSide();
                }

                if ((lce != null || rce != null) && (IsArithIdentity(lce, rce)))
                {
                    return(SimplifyArithmetic(lce, rce));
                }

                if (IsLogicalOp())
                {
                    return(SimplifyLogic());
                }

                if (IsRelOp())
                {
                    return(SimplifyRelop());
                }

                // arithmetic operators?
                if (l is BinExpr le && le.children_[1].IsConst() && (rce != null) &&
                    isCommutativeConstOp() && le.isCommutativeConstOp() && TypeBase.SameArithType(l.type_, r.type_))
                {
                    /*
                     * Here root is distributive operator (only * in this context) left is Commutative
                     * operator, +, or * right is constant, furthermore, left's right is a constant
                     * (becuase we swapped cosntant to be on the right).
                     * if be == + and l == +: add left's right value to root's right value,
                     * make  left's left as left of root
                     *
                     * if be == * and l == +: create a expr node as left (x + 10), create (5 * 10)
                     * as right, change operator to +
                     * In either case left and right's children must be nulled out
                     * and since we are going bottom up, this doesn't create any problem.
                     *
                     * Here is a pictorial description:
                     *                         *         root           +
                     *              old left  / \ old right   new left / \  new right
                     *                       /   \                    /   \
                     *                      +     10        =>       *     50
                     *  left of old left   / \                      / \
                     *                    /   \ ROL         LNL    /   \ RNL (right of New Left)
                     *                   x     5                  x     10
                     */

                    /*
                     * Simple case: when current and left are same operators, distributive
                     * opeartion and node creation is uncessary.
                     */
                    if ((op_ == "+" && le.op_ == "+") || (op_ == "*" && le.op_ == "*"))
                    {
                        /* create new right node as constant. */
                        Expr tmpexp = Clone();
                        tmpexp.children_[0] = le.children_[1];
                        tmpexp.children_[1] = r;
                        tmpexp.type_        = r.type_;

                        Value val;
                        bool  wasConst = tmpexp.TryEvalConst(out val);
                        Expr  newr     = ConstExpr.MakeConst(val, tmpexp.type_, r.outputName_);

                        // new left is old left's left child
                        // of left will be right of the root.
                        children_[0] = l.children_[0];

                        // new right is the new constant node
                        children_[1] = newr;
                    }
                    else
                    if (op_ == "*" && le.rchild_() is ConstExpr lrc && (le.op_ == "+" || le.op_ == "-"))
                    {
                        /*
                         * case of (a + const1) * const2  => (a * const2) + (const1 * const2))
                         * make a newe left node to house (a * const2)
                         *
                         *                          *                    +
                         *                         / \                  / \
                         *                        /   \                /   \
                         *                       +     c2     =>      *   c1 * c2
                         *                      / \                  / \
                         *                     /   \                /   \
                         *                    X     c1             X     c2
                         *
                         */

                        /* make a const expr node to evaluate const1 * const 2 */
                        Expr tmpexp = Clone();
                        tmpexp.children_[0] = lrc;      // right of left is const
                        tmpexp.children_[1] = r;        // our right is const
                        tmpexp.type_        = r.type_;

                        Value val;
                        tmpexp.TryEvalConst(out val);

                        // set c2 as the value of right child of our left
                        lrc.val_ = rce.val_;

                        // val is c1 * c2, set it as the value of our right child
                        rce.val_ = val;

                        /* swap the operators */
                        string op = op_;
                        op_    = le.op_;
                        le.op_ = op;
                    }
                    /* we can't do any thing about + at the top and * as left child. */
                }

                return(this);
            }

            return(this);
        }