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); } }
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); }