Beispiel #1
0
        // Arthmentic Simplification:

        /*
         * +/- zero to a column, or multiply/divide a column by 1
         */
        internal bool IsArithIdentity(ConstExpr lce, ConstExpr rce)
        {
            ConstExpr ve = lce != null ? lce : rce;
            ColExpr   ce = (children_[0] is ColExpr) ? (ColExpr)children_[0] : (children_[1] is ColExpr ? (ColExpr)children_[1] : null);

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

            if (!(TypeBase.IsNumberType(ve.type_) && TypeBase.IsNumberType(ce.type_)))
            {
                return(false);
            }

            if ((op_ == "+" || op_ == "-") && ve.IsZero())
            {
                return(true);
            }

            if ((op_ == "*" || op_ == "/") && ve.IsOne())
            {
                return(true);
            }

            return(false);
        }
Beispiel #2
0
        public override void Bind(BindContext context)
        {
            base.Bind(context);

            // derive return type
            Debug.Assert(lchild_().type_ != null && rchild_().type_ != null);
            switch (op_)
            {
            case "+":
            case "-":
            case "*":
            case "/":
            case "||":
                // notice that CoerseType() may change l/r underneath
                type_ = ColumnType.CoerseType(op_, lchild_(), rchild_());
                break;

            case ">":
            case ">=":
            case "<":
            case "<=":
                if (TypeBase.IsNumberType(lchild_().type_))
                {
                    ColumnType.CoerseType(op_, lchild_(), rchild_());
                }
                else if (TypeBase.OnlyOneIsStringType(lchild_().type_, rchild_().type_))
                {
                    throw new SemanticAnalyzeException("no implicit conversion of character type values");
                }
                type_ = new BoolType();
                break;

            case "=":
            case "<>":
            case "!=":
                if (TypeBase.IsNumberType(lchild_().type_))
                {
                    ColumnType.CoerseType(op_, lchild_(), rchild_());
                }
                else if (TypeBase.OnlyOneIsStringType(lchild_().type_, rchild_().type_))
                {
                    throw new SemanticAnalyzeException("no implicit conversion of character type values");
                }
                type_ = new BoolType();
                break;

            case " and ":
            case " or ":
            case "like":
            case "not like":
            case "in":
            case "is":
            case "is not":
                type_ = new BoolType();
                break;

            default:
                throw new NotImplementedException();
            }
        }
Beispiel #3
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);
        }