예제 #1
0
파일: Impl.cs 프로젝트: WVitek/DotGlue
        static bool TryExtractTimeFormatString(Expr timeExpr, out Expr fieldExpr, out string timeFmtStr)
        {
            fieldExpr  = timeExpr;
            timeFmtStr = null;
            if (timeExpr.nodeType != ExprType.Call)
            {
                return(false);
            }
            Expr      field      = null;
            ConstExpr timeFmt    = ConstExpr.Null;
            bool      withToDate = timeExpr.Traverse(e =>
            {
                if (e.nodeType != ExprType.Call)
                {
                    return(false);
                }
                var ce = e as CallExpr;
                if (ce == null || ce.args.Count < 2 || string.Compare(ce.funcName, "TO_DATE", StringComparison.OrdinalIgnoreCase) != 0)
                {
                    return(false);
                }
                field   = ce.args[0];
                timeFmt = (ConstExpr)ce.args[1];
                return(true);
            }).Any(f => f);

            if (!withToDate)
            {
                return(false);
            }
            fieldExpr  = field;
            timeFmtStr = Convert.ToString(timeFmt.value);
            return(true);
        }
예제 #2
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);
        }
예제 #3
0
        public void ElementCreate()
        {
            Element e = new Element(3.141592);
            Assert.IsNotNull(e);

            Element p = new Element(100);
            Element q = new Element(p);
            Element z = new Element(DateTime.Now);

            ConstExpr j = new ConstExpr(z);
            ConstExpr k = new ConstExpr(j.Value.BoolValue());

            ConstExpr v = new ConstExpr(k);
            ConstExpr u = new ConstExpr(v);

            Element b = new Element(true);
            Element i = new Element(100);
            Element l = new Element(9812080980101);
            Element d = new Element(3.1314);
            Element s = new Element("Hello World!");
            Element dt = new Element(DateTime.Now);
            Element ts = new Element(TimeSpan.FromSeconds(100));
            Element r = new Element(new Regex("abc[0-9]"));

            Assert.IsTrue(b.DataType == ElementType.BOOL);
            Assert.IsTrue(l.DataType == ElementType.LONG);
            Assert.IsTrue(d.DataType == ElementType.DOUBLE);
            Assert.IsTrue(s.DataType == ElementType.STRING);
            Assert.IsTrue(dt.DataType == ElementType.DATETIME);
            Assert.IsTrue(ts.DataType == ElementType.TIMESPAN);
            Assert.IsTrue(r.DataType == ElementType.REGEX);
        }
예제 #4
0
 public override Expression Evaluate(EvalStore store)
 {
     ConstExpr e = (ConstExpr)this.Arguments[0].Evaluate(store);
     if (e.Value.DataType == ElementType.LONG) {
         if (e.Value.LongValue() < 0) e = new ConstExpr(-e.Value.LongValue());
     }
     else if (e.Value.DataType == ElementType.DOUBLE) {
         if (e.Value.DoubleValue() < 0) e = new ConstExpr(-e.Value.DoubleValue());
     }
     return e;
 }
예제 #5
0
        public override Expr Normalize()
        {
            Expr x = base.Normalize();

            if (x.AllArgsConst())
            {
                Value val = Exec(null, null);
                return(ConstExpr.MakeConst(val, type_, outputName_));
            }

            // NOT NOT X => X
            if (op_ == "!")
            {
                if (child_() is UnaryExpr ue && ue.op_ == "!")
                {
                    return(ue.child_());
                }

                // NOT (X AND Y)    => NOT A OR NOT B
                // NOT (X OR Y)     => NOT A AND NOT B

                /*
                 *           NOT                  OR
                 *            |                  /  \
                 *           AND      =>       NOT    NOT
                 *          /    \              |      |
                 *         X      Y             X      Y
                 */

                if (child_() is LogicAndOrExpr le)
                {
                    // Make two Unary expressions for NOT X and NOT Y
                    // Cloning avoids messing with bounded_ flag
                    UnaryExpr nlu = (UnaryExpr)Clone();
                    UnaryExpr nru = (UnaryExpr)Clone();

                    // get the new logical operator, reverse of current one
                    string nop = le.op_ == " and " ? " or " : " and ";

                    // save X, Y
                    Expr ole = le.lchild_();
                    Expr ore = le.rchild_();

                    // New Unary nodes point to old left and right
                    // logical expressions.
                    nlu.children_[0] = ole;
                    nru.children_[0] = ore;

                    return(makeAnyLogicalExpr(nlu, nru, nop));
                }
            }

            return(x);
        }
예제 #6
0
 static void AttrsToComments <T>(this IEnumerable <KeyValuePair <T, object> > attrs, TextWriter wr)
 {
     foreach (var p in attrs)
     {
         wr.Write("--");
         wr.Write(p.Key);
         wr.Write('=');
         ConstExpr.ToText(wr, p.Value);
         wr.WriteLine();
     }
 }
예제 #7
0
        static void Main(string[] args)
        {
            Console.WriteLine("1_______________________________________________________________________________");
            // (3*x^2 + 7) / (x + 5)   82 / 10 = 8.2
            Expression exp = new DivExpr(
                new AddExpr(
                    MonomialExpr.createObject(3, 2),
                    ConstExpr.createObject(7)),
                new AddExpr(
                    MonomialExpr.createObject(1, 1),
                    ConstExpr.createObject(5)));

            Console.WriteLine("f(x)=" + exp.ToString());
            Console.WriteLine("f(5)=" + exp.Evaluate(5));
            Console.WriteLine("f'(x)=" + exp.Derive().ToString());

            Console.WriteLine("2_______________________________________________________________________________");
            // (0 + 10) - 0 * (x^1 + 0)
            Expression exp5 = new AddExpr(MonomialExpr.createObject(0, 2),
                                          ConstExpr.createObject(10));

            Expression exp6 = new SubExpr(exp5,
                                          new MulExpr(ConstExpr.createObject(0),
                                                      new AddExpr(MonomialExpr.createObject(1, 1),
                                                                  ConstExpr.createObject(0))));

            Console.WriteLine("f(x)=" + exp6.ToString());
            Console.WriteLine("f(2)=" + exp6.Evaluate(2));
            Console.WriteLine("f'(x)=" + exp6.Derive().ToString());


            Console.WriteLine("3_______________________________________________________________________________");
            //(((x^2 + 2) / (x + 1)) + 10) / (x^2 + 5)
            Expression exp3 = new DivExpr(
                new AddExpr(
                    MonomialExpr.createObject(1, 2),
                    ConstExpr.createObject(2)),
                new AddExpr(
                    MonomialExpr.createObject(1, 1),
                    ConstExpr.createObject(1)));

            Expression exp4 = new DivExpr(
                new AddExpr(
                    exp3,
                    ConstExpr.createObject(10)),
                new AddExpr(
                    MonomialExpr.createObject(1, 2),
                    ConstExpr.createObject(5)));

            Console.WriteLine("f(x)=" + exp4.ToString());
            Console.WriteLine("f(1)=" + exp4.Evaluate(1));
            Console.WriteLine("f'(x)=" + exp4.Derive().ToString());
        }
예제 #8
0
        public override Expr Normalize()
        {
            Expr x = base.Normalize();

            if (!x.AllArgsConst() || ExternalFunctions.set_.ContainsKey(funcName_))
            {
                return(this);
            }

            if (x.AnyArgNull())
            {
                return(ConstExpr.MakeConst("null", new AnyType(), outputName_));
            }

            switch (funcName_)
            {
            case "min":
            case "max":
            case "avg":
                return(child_());

            case "sum":
            case "count":
            case "count(*)":
            case "coalesce":
            case "tumble":
            case "tumble_start":
            case "tumble_end":
            case "hop":
            case "session":
            case "stddev_samp":
                return(this);

            default:
                break;
            }

            Value val = Exec(null, null);

            return(ConstExpr.MakeConst(val, type_, outputName_));
        }
예제 #9
0
        internal Expr SimplifyArithmetic(ConstExpr lve, ConstExpr rve)
        {
            // we know we have a BinExpr with numeric children
            ConstExpr ve = lve != null ? lve : rve;
            ColExpr   ce = (children_[0] is ColExpr) ? (ColExpr)children_[0] : (children_[1] is ColExpr ? (ColExpr)children_[1] : null);

            if (ce is null || ve is null)
            {
                return(this);
            }

            // Col + 0, or Col - 0 => return col
            if ((op_ == "+" || op_ == "-") && ve.IsZero())
            {
                return(ce);
            }

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

            return(this);
        }
예제 #10
0
            IEnumerable <(CellRange cell, Expr expr)> DumpDepsImpl(string forCell)
            {
                if (already.ContainsKey(forCell))
                {
                    yield break;
                }
                already.Add(forCell, true);
                var rng = CellRange.TryFromName(forCell);

                if (rng == null)
                {
                    yield break;
                }
                Expr expr;

                if (sheet.fmls.TryGetValue(rng, out expr))
                {
                    // Make all cell references relative
                    expr = Expr.RecursiveModifier(XlsxR.RangeRefToRelativeModifier)(expr);
                    foreach (var s in expr.EnumerateReferences())
                    {
                        foreach (var dep in DumpDepsImpl(s))
                        {
                            yield return(dep);
                        }
                    }
                }
                else if (!sheet.vals.TryGetValue(rng, out expr))
                {
                    expr = new ConstExpr("??? (value not found)");
                }
                if (forCell == null)
                {
                }
                yield return(rng, expr);
            }
    //--------------------------------------------------------------------
    #region 内部方法
    ExprBase Parse(Queue <string> stringQueue)
    {
        string   word = null;
        ExprBase first = null, prev = null, last = null;

        while (stringQueue.Count > 0)
        {
            word = stringQueue.Dequeue();
            if (word == "(")
            {
                ExprBase subExpr = Parse(stringQueue);
                if (subExpr == null)
                {
                    return(null);
                }
                last = new SubExpr(subExpr);
            }
            else if (word[0] == '\'')
            {
                int endPos = word.LastIndexOf('\'');
                if (endPos > 0)
                {
                    last = new StrExpr(word.Substring(1, endPos - 1));
                }
                else
                {
                    return(null);
                }
            }
            else if (word[0] == '\"')
            {
                int endPos = word.LastIndexOf('\"');
                if (endPos > 0)
                {
                    last = new StrExpr(word.Substring(1, endPos - 1));
                }
                else
                {
                    return(null);
                }
            }
            else if (word == "true")
            {
                last = new ConstExpr(1);
            }
            else if (word == "false")
            {
                last = new ConstExpr(0);
            }
            else if (word[0] == '-' || Char.IsDigit(word[0]))
            {
                if (word.Contains("."))
                {
                    last = new ConstExpr(float.Parse(word));
                }
                else
                {
                    last = new ConstExpr(int.Parse(word));
                }
            }
            else
            {
                last = ParseFunc(word, stringQueue);
            }

            if (last == null)
            {
                return(null);
            }

            if (first == null)
            {
                first = prev = last;
            }
            else
            {
                prev.next = last;
                prev      = last;
            }

            // 条件连接关系
            if (stringQueue.Count > 0)
            {
                word = stringQueue.Dequeue();
                if (word == ")")
                {
                    break;
                }

                last.connector = ExprConnectors.Get(word);
                if (last.connector == null)
                {
                    return(null);
                }
            }

            last = null;
        }
        return(first);
    }
        public Expression GetNode(ExpressionParser parser)
        {
            var        collection = parser.Collection;
            Lexem      lex        = parser.Collection.CurrentLexem();
            bool       uniar      = parser.waitValue;
            Expression res        = null;

            if (lex.LexemType == LexType.Arfimetic)
            {
                switch (lex.LexemText)
                {
                case "+":
                    if (uniar)
                    {
                        res = new UniarPlus_BoolExpr();
                    }
                    else
                    {
                        res = new Plus_Arifmetic();
                    }
                    break;

                case "-":
                    if (uniar)
                    {
                        res = new UniarMinus_BoolExpr();
                    }
                    else
                    {
                        res = new Minus_Arifmetic();
                    }
                    break;

                case "*":
                    if (uniar)
                    {
                        res = new AllColumnExpr();
                    }
                    else
                    {
                        res = new Multi_Arifmetic();
                    }
                    break;

                case "/":
                    res = new Div_Arifmetic();
                    break;

                case "<":
                    res = new Less_CompExpr();
                    break;

                case "<=":
                    res = new LessOrEqual_CompExpr();
                    break;

                case ">=":
                    res = new GreatOrEqual_CompExpr();
                    break;

                case ">":
                    res = new Great_CompExpr();
                    break;

                case "=":
                    res = new Equal_CompExpr();
                    break;

                case "<>":
                case "!=":
                    res = new NotEqual_CompExpr();
                    break;
                }
            }
            if (lex.LexemType == LexType.Number)
            {
                res = new ConstExpr();
                if (lex.LexemText.Contains('.'))
                {
                    (res as ConstExpr).Init(lex.LexemText.ParseDouble(), SimpleTypes.Float);
                }
                else
                {
                    (res as ConstExpr).Init(long.Parse(lex.LexemText), SimpleTypes.Integer);
                }
            }
            if (lex.LexemType == LexType.Text)
            {
                if (lex.LexemText.StartsWith("'"))
                {
                    res = new ConstExpr();
                    (res as ConstExpr).Init(ParserUtils.StandartDecodeEscape(lex.LexemText), SimpleTypes.String);
                }
            }
            if (lex.LexemType == LexType.Command)
            {
                switch (lex.LexemText.ToLower())
                {
                case "not":
                    res = new Not_BoolExpr();
                    break;

                case "and":
                    res = new And_BoolExpr();
                    break;

                case "or":
                    res = new Or_BoolExpr();
                    break;

                case "true":
                    res = new ConstExpr();
                    (res as ConstExpr).Init(true, SimpleTypes.Boolean);
                    break;

                case "false":
                    res = new ConstExpr();
                    (res as ConstExpr).Init(false, SimpleTypes.Boolean);
                    break;

                case "date":
                    if (collection.GetNext() != null)
                    {
                        var c = collection.GetNext();
                        if (c.LexemType == LexType.Text && c.LexemText.StartsWith("'"))
                        {
                            res = new ConstExpr();
                            string s  = ParserUtils.StandartDecodeEscape(c.LexemText);
                            var    dt = CommonUtils.ParseDateTime(s);
                            if (dt != null)
                            {
                                collection.GotoNext();
                                ((ConstExpr)res).Init(dt.Value, SimpleTypes.Date);
                            }
                            else
                            {
                                collection.Error("Can not parse date lexem", lex);
                            }
                        }
                    }
                    break;

                case "datetime":
                case "timestamp":
                    if (collection.GetNext() != null)
                    {
                        var c = collection.GetNext();
                        if (c.LexemType == LexType.Text && c.LexemText.StartsWith("'"))
                        {
                            res = new ConstExpr();
                            string s  = ParserUtils.StandartDecodeEscape(c.LexemText);
                            var    dt = CommonUtils.ParseDateTime(s);
                            if (dt != null)
                            {
                                collection.GotoNext();
                                ((ConstExpr)res).Init(dt.Value, SimpleTypes.DateTime);
                            }
                            else
                            {
                                collection.Error("Can not parse datetime lexem", lex);
                            }
                        }
                    }
                    break;

                case "time":
                    if (collection.GetNext() != null)
                    {
                        var c = collection.GetNext();
                        if (c.LexemType == LexType.Text && c.LexemText.StartsWith("'"))
                        {
                            res = new ConstExpr();
                            string   s = ParserUtils.StandartDecodeEscape(c.LexemText);
                            DateTime dt;
                            var      r = CommonUtils.ParseDateTime(s, out dt);
                            if (r == ParserDateTimeStatus.Time)
                            {
                                collection.GotoNext();
                                ((ConstExpr)res).Init(dt.TimeOfDay, SimpleTypes.Time);
                            }
                            else
                            {
                                collection.Error("Can not parse time lexem", lex);
                            }
                        }
                    }
                    break;
                }
            }
            return(res);
        }
예제 #13
0
        protected Expression DoOptimize(out bool changed)
        {
            changed = false;
            if (Childs != null)
            {
                for (int i = 0; i < Childs.Count; i++)
                {
                    bool ch;
                    Childs[i] = Childs[i].DoOptimize(out ch);
                    if (ch)
                    {
                        changed = true;
                    }
                }
            }
            if (OnlyOnline() && !(this is ConstExpr))
            {
                ConstExpr ce = CreateConst();
                switch (GetResultType())
                {
                case SimpleTypes.Boolean:
                    ce.Init(GetBoolResultOut(null), SimpleTypes.Boolean);
                    break;

                case SimpleTypes.Date:
                    ce.Init(GetDateTimeResultOut(null), SimpleTypes.Date);
                    break;

                case SimpleTypes.DateTime:
                    ce.Init(GetDateTimeResultOut(null), SimpleTypes.DateTime);
                    break;

                case SimpleTypes.Float:
                    ce.Init(GetFloatResultOut(null), SimpleTypes.Float);
                    break;

                case SimpleTypes.String:
                    ce.Init(GetStrResultOut(null), SimpleTypes.String);
                    break;

                case SimpleTypes.Time:
                    ce.Init(GetTimeResultOut(null), SimpleTypes.Time);
                    break;

                case SimpleTypes.Integer:
                    ce.Init(GetIntResultOut(null), SimpleTypes.Integer);
                    break;

                case SimpleTypes.Blob:
                    ce.Init(GetBlobResultOut(null), SimpleTypes.Blob);
                    break;

                case SimpleTypes.Geometry:
                    ce.Init(GetGeomResultOut(null), SimpleTypes.Geometry, GetCoordinateSystem());
                    break;
                }
                changed = true;
                return(ce);
            }
            return(this);
        }
예제 #14
0
        // D Xs (Filter(T)) => Filter(D Xs T)
        LogicNode djoinOnRightFilter(LogicSingleJoin singleJoinNode, ScalarSubqueryExpr scalarExpr)
        {
            var nodeLeft           = singleJoinNode.lchild_();
            var nodeSubquery       = singleJoinNode.rchild_();
            var nodeSubqueryFilter = nodeSubquery.filter_;

            Debug.Assert(scalarExpr.query_.selection_.Count == 1);
            var singleValueExpr = scalarExpr.query_.selection_[0];

            nodeSubquery.NullifyFilter();

            // nullify nodeA's filter: the rest is push to top filter. However,
            // if nodeA is a Filter|MarkJoin, keep its mark filter.
            var trueCondition  = ConstExpr.MakeConstBool(true);
            var nodeLeftFilter = nodeLeft.filter_;

            if (nodeLeftFilter != null)
            {
                // a1 > @1 and a2 > @2 and a3 > 2, scalarExpr = @1
                //   keeplist: a1 > @1 and a3 > 2
                //   andlist after removal: a2 > @2
                //   nodeAFilter = a1 > @1 and a3 > 2
                //
                var andlist  = nodeLeftFilter.FilterToAndList();
                var keeplist = andlist.Where(x => x.VisitEachExists(e => e.Equals(scalarExpr))).ToList();
                andlist.RemoveAll(x => x.VisitEachExists(e => e.Equals(scalarExpr)));
                if (andlist.Count == 0)
                {
                    nodeLeft.NullifyFilter();
                }
                else
                {
                    nodeLeft.filter_ = andlist.AndListToExpr();
                    if (keeplist.Count > 0)
                    {
                        nodeLeftFilter = keeplist.AndListToExpr();
                    }
                    else
                    {
                        nodeLeftFilter = trueCondition;
                    }
                }
            }

            // make a non-movable filter on top of the single join to replace a1 > @1
            LogicFilter nonMovableFilter = null;

            if (nodeLeftFilter != null)
            {
                // a1 > @1 => a1 > c1
                var decExpr = nodeLeftFilter.SearchAndReplace(scalarExpr, singleValueExpr);
                nonMovableFilter = new LogicFilter(singleJoinNode, decExpr)
                {
                    movable_ = false
                };
            }

            // b1 = ?outsideRef => b1 = outsideRef
            nodeSubqueryFilter.DeParameter(nodeLeft.InclusiveTableRefs());

            // join filter within sbuquery
            Expr pullupFilter = nodeSubqueryFilter;

            if (nodeLeft.filter_ != null && !nodeLeft.filter_.HasSubQuery())
            {
                pullupFilter = pullupFilter.AddAndFilter(nodeLeft.filter_);
                nodeLeft.NullifyFilter();
            }
            LogicFilter Filter = new LogicFilter(nonMovableFilter != null ?
                                                 (LogicNode)nonMovableFilter : singleJoinNode, pullupFilter);

            return(Filter);
        }
예제 #15
0
        public Expression GetNode(ExpressionParser parser)
        {
            Lexem      lex   = parser.Collection.CurrentLexem();
            Expression ex    = null;
            bool       uniar = parser.waitValue;

            if (lex.LexemType == LexType.Arfimetic)
            {
                switch (lex.LexemText)
                {
                case "+":
                    if (uniar)
                    {
                        ex = new UniarPlus_BoolExpr();
                    }
                    else
                    {
                        ex = new Plus_Arifmetic();
                    }
                    break;

                case "-":
                    if (uniar)
                    {
                        ex = new UniarMinus_BoolExpr();
                    }
                    else
                    {
                        ex = new Minus_Arifmetic();
                    }
                    break;

                case "*":
                    if (uniar)
                    {
                        ex = new AllColumnExpr();
                    }
                    else
                    {
                        ex = new Multi_Arifmetic();
                    }
                    break;

                case "/":
                    ex = new Div_Arifmetic();
                    break;

                case "<":
                    ex = new Less_CompExpr();
                    break;

                case "<=":
                    ex = new LessOrEqual_CompExpr();
                    break;

                case ">=":
                    ex = new GreatOrEqual_CompExpr();
                    break;

                case ">":
                    ex = new Great_CompExpr();
                    break;

                case "=":
                    ex = new Equal_CompExpr();
                    break;

                case "<>":
                case "!=":
                    ex = new NotEqual_CompExpr();
                    break;
                }
            }
            if (lex.LexemType == LexType.Number)
            {
                ex = new ConstExpr();
                if (lex.LexemText.Contains('.'))
                {
                    (ex as ConstExpr).Init(lex.LexemText.ParseDouble(), SimpleTypes.Float);
                }
                else
                {
                    (ex as ConstExpr).Init(long.Parse(lex.LexemText), SimpleTypes.Integer);
                }
            }
            if (lex.LexemType == LexType.Text)
            {
                if (lex.LexemText.StartsWith("'"))
                {
                    ex = new ConstExpr();
                    (ex as ConstExpr).Init(ParserUtils.StandartDecodeEscape(lex.LexemText), SimpleTypes.String);
                }
            }
            Lexem n1;

            if (lex.LexemType == LexType.Command)
            {
                switch (lex.LexemText.ToLower())
                {
                case "not":
                    n1 = parser.Collection.GetNext();
                    if (n1 != null && n1.LexemType == LexType.Command && n1.LexemText.ToLower() == "in")
                    {
                        ex = new NotInExpr();
                        parser.Collection.GotoNext();
                        break;
                    }
                    ex = new Not_BoolExpr();
                    break;

                case "case":
                    ex = new CaseExpr();
                    break;

                case "contains":
                    ex = new Contains();
                    break;

                case "containsic":     //ic = ignore case
                case "containscase":
                    ex = new ContainsIgnoreCase();
                    break;

                case "startwith":
                case "startswith":
                    ex = new StartsWith();
                    break;

                case "endwith":
                case "endswith":
                    ex = new EndsWith();
                    break;
                }
                if (parser.Collection.GetNext() != null && parser.Collection.GetNext().IsSkobraOpen())
                {
                    switch (lex.LexemText.ToLower())
                    {
                    case "cast":
                        ex = new Cast();
                        break;

                    case "in":
                        ex = new InExpr();
                        break;

                    case "abs":
                        ex = new Abs();
                        break;

                    case "substring":
                        ex = new SubString();
                        break;

                    case "position":
                        ex = new Position();
                        break;

                    case "ltrim":
                        ex = new LTrim();
                        break;

                    case "rtrim":
                        ex = new RTrim();
                        break;

                    case "trim":
                        ex = new Trim();
                        break;

                    case "length":
                        ex = new Length();
                        break;

                    case "upper":
                        ex = new Upper_operation();
                        break;

                    case "lower":
                        ex = new Lower_operation();
                        break;

                    case "left":
                        ex = new Left();
                        break;

                    case "right":
                        ex = new Right();
                        break;

                    case "replace":
                        ex = new Replace();
                        break;

                    case "now":
                        ex = new Now();
                        break;

                    case "tostr":
                        ex = new ToString();
                        break;

                    case "strtotime":
                        ex = new StrToTime();
                        break;

                    case "strtodatetime":
                        ex = new StrToDateTime();
                        break;

                    case "addseconds":
                        ex = new AddSeconds();
                        break;

                    case "addminutes":
                        ex = new AddMinutes();
                        break;

                    case "addhours":
                        ex = new AddHours();
                        break;

                    case "adddays":
                        ex = new AddDays();
                        break;

                    case "day":
                        ex = new Day();
                        break;

                    case "month":
                        ex = new Month();
                        break;

                    case "year":
                        ex = new Year();
                        break;

                    case "round":
                        ex = new ParserCore.Expr.Extend.Math.Round();
                        break;

                    case "ceiling":
                        ex = new ParserCore.Expr.Extend.Math.Ceiling();
                        break;

                    case "floor":
                        ex = new ParserCore.Expr.Extend.Math.Floor();
                        break;

                    case "pi":
                        ex = new ParserCore.Expr.Extend.Math.Pi();
                        break;

                    case "tan":
                        ex = new ParserCore.Expr.Extend.Math.Tan();
                        break;

                    case "log":
                        ex = new ParserCore.Expr.Extend.Math.Log();
                        break;
                    }
                }
            }
            return(ex);
        }
예제 #16
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);
                }
            }
예제 #17
0
        // expands [NOT] EXISTS filter to mark join
        //
        //  LogicNode_A
        //     Filter: @1 AND|OR <others1>
        //     <ExistSubqueryExpr> 1
        //          -> LogicNode_B
        //             Filter: b.b1[0]=?a.a1[0] AND|OR <others2>
        // =>
        //    Filter
        //      Filter: #marker AND|OR <others1>
        //      MarkJoin
        //         Filter:  (b.b1[0]=a.a1[0]) AND|OR <others2> as #marker
        //         LogicNode_A
        //         LogicNode_B
        //
        // further convert DJoin to semi-join here is by decorrelate process
        //
        LogicNode existsToMarkJoin(LogicNode nodeA, ExistSubqueryExpr existExpr)
        {
            var nodeAIsOnMarkJoin =
                nodeA is LogicFilter && (nodeA.child_() is LogicMarkJoin || nodeA.child_() is LogicSingleJoin);

            // nodeB contains the join filter
            var nodeB       = existExpr.query_.logicPlan_;
            var nodeBFilter = nodeB.filter_;

            nodeB.NullifyFilter();

            // nullify nodeA's filter: the rest is push to top filter. However,
            // if nodeA is a Filter|MarkJoin, keep its mark filter.
            var markerFilter = new ExprRef(new MarkerExpr(), 0);
            var nodeAFilter  = nodeA.filter_;

            if (nodeAIsOnMarkJoin)
            {
                nodeA.filter_ = markerFilter;
            }
            else
            {
                if (nodeAFilter != null)
                {
                    // a1 > @1 and a2 > @2 and a3 > 2, scalarExpr = @1
                    //   keeplist: a1 > @1 and a3 > 2
                    //   andlist after removal: a2 > @2
                    //   nodeAFilter = a1 > @1 and a3 > 2
                    //
                    var andlist  = nodeAFilter.FilterToAndList();
                    var keeplist = andlist.Where(x => x.VisitEachExists(e => e.Equals(existExpr))).ToList();
                    andlist.RemoveAll(x => x.VisitEachExists(e => e.Equals(existExpr)));
                    if (andlist.Count == 0)
                    {
                        nodeA.NullifyFilter();
                    }
                    else
                    {
                        nodeA.filter_ = andlist.AndListToExpr();
                        if (keeplist.Count > 0)
                        {
                            nodeAFilter = keeplist.AndListToExpr();
                        }
                        else
                        {
                            nodeAFilter = markerFilter;
                        }
                    }
                }
            }
            // make a mark join
            LogicMarkJoin markjoin;

            if (existExpr.hasNot_)
            {
                markjoin = new LogicMarkAntiSemiJoin(nodeA, nodeB);
            }
            else
            {
                markjoin = new LogicMarkSemiJoin(nodeA, nodeB);
            }

            // make a filter on top of the mark join collecting all filters
            Expr topfilter;

            if (nodeAIsOnMarkJoin)
            {
                topfilter = nodeAFilter.SearchAndReplace(existExpr, ConstExpr.MakeConstBool(true));
            }
            else
            {
                topfilter = nodeAFilter.SearchAndReplace(existExpr, markerFilter);
            }
            nodeBFilter.DeParameter(nodeA.InclusiveTableRefs());
            topfilter = topfilter.AddAndFilter(nodeBFilter);
            LogicFilter Filter = new LogicFilter(markjoin, topfilter);

            return(Filter);
        }
예제 #18
0
            public ModifyHelper()
            {
                modify = Expr.RecursiveModifier(e =>
                {
                    if (e.nodeType == ExprType.Reference || e.nodeType == ExprType.Constant)
                    {
                        return(e);
                    }
                    if (e.nodeType != ExprType.Call)
                    {
                        goto tryConst;
                    }
                    var ce     = (CallExpr)e;
                    bool isLet = ce.funcName == "let";
                    bool isDef = isLet || ce.funcName == "SV" || ce.funcName == "SSV";
                    if (!isDef && ce.funcName != "GV" && ce.funcName != "GSV")
                    {
                        goto tryConst;
                    }
                    var arg0 = ce.args[0];
                    string name;
                    if (arg0.nodeType == ExprType.Constant)
                    {
                        name = Convert.ToString((arg0 as ConstExpr).value);
                        if (!isLet && ce.args.Count == 1)
                        {
                            e = new ReferenceExpr(name);
                        }
                        goto constResolved;
                    }
                    if (arg0.nodeType == ExprType.Reference)
                    {
                        name = (arg0 as ReferenceExpr).name;
                        goto nameResolved;
                    }
                    // try to resolve name
                    var nameObj = TryGen(ctx, arg0);
                    if (nameObj == Fail || OPs.KindOf(nameObj) != ValueKind.Const)
                    {
                        thereIsNonresolved = true;
                        return(e);
                    }
                    name = Convert.ToString(nameObj);
                    thereIsNameResolve = true;
                    constResolved:
                    var args = new Expr[ce.args.Count];
                    if (isLet)
                    {
                        args[0] = new ReferenceExpr(name);
                    }
                    else
                    {
                        if (ce.args.Count == 1 && ce.funcName != "GSV")
                        {
                            return(new ReferenceExpr(name));
                        }
                        args[0] = new ConstExpr(name);
                    }
                    for (int i = 1; i < args.Length; i++)
                    {
                        args[i] = modify(ce.args[i]);
                    }
                    e = new CallExpr(ce.funcName, args);
                    nameResolved:
                    if (isDef && ce.args.Count == 2)
                    {
                        lets.Add(name);
                        //var value = modify(ce.args[1]);
                        //if (value.nodeType == ExprType.Constant)
                        //{ }
                    }
                    return(e);

                    tryConst:
                    var val = TryGen(ctx, e);
                    if (val == Fail || OPs.KindOf(val) != ValueKind.Const)
                    {
                        return(e);
                    }
                    return(new ConstExpr(val));
                });
            }
예제 #19
0
            Expr SpecFuncs(CallExpr ce)
            {
                Expr src, ndx;
                bool forPrev = false, forCell = false;
                int  nMinArgs = 1;

                switch (ce.funcName)
                {
                case "PREVCELL":
                    forCell = true; forPrev = true; break;

                case "PREV":
                    nMinArgs = 0; forPrev = true; break;

                case "INDIRECT":
                    forCell = true; break;

                case nameof(FuncDefs_Xlsx.COLUMN):
                    // avoid COLUMN(args) fixing
                    return(new CallExpr(nameof(FuncDefs_Xlsx.COLUMN), ce.args));

                default:
                    return(ce);
                }
                if (ce.args.Count < nMinArgs)
                {
                    return(ce);
                }

                Expr   arg;
                string name;

                if (ce.args.Count == 0)
                {
                    arg  = null;
                    name = FCurrName;
                }
                else
                {
                    arg = ce.args[0];
                    if (arg.nodeType == ExprType.Reference)
                    {
                        name = ((ReferenceExpr)arg).name;
                        if (IsColumnName(name) || !forPrev && IsFullRelativeCell(CellRange.FromName(name)))
                        {
                            forCell = true;
                        }
                        else
                        {
                            name = OPs.TryAsString(arg, ctxRow) ?? name;
                        }
                    }
                    else
                    {
                        arg  = FixRowExpr(arg);
                        name = OPs.TryAsName(arg, ctxRow);
                    }
                }

                if (name == null)
                {
                    var undefs = string.Join(", ", ctxHdr.NamesOfUndefinedValues().Concat(ctxRow.NamesOfUndefinedValues()));
                    throw new Source.Exception($"Constant expected as value of {ce.args[0]}={arg} // ??? {undefs}");
                }

                if (forCell || IsColumnName(name) || !forPrev && IsFullRelativeCell(CellRange.FromName(name)))
                {
                    if (forPrev)
                    {
                        src = new IndexExpr(PrevValsRef, new ConstExpr(ctxRow.IndexOf(CellValsRef.name)));
                    }
                    else
                    {
                        var re1 = new ReferenceExpr(name);
                        var re2 = FixHdrCellRef(re1);
                        if (re2 != re1)
                        {
                            // ref to header cell
                            return(re2);
                        }
                        else
                        {
                            // ref to row cell
                            src = CellValsRef;
                        }
                    }
                    ndx = new ConstExpr(name);
                }
                else
                {
                    int i = ctxRow.IndexOf(name);
                    if (i < 0 || Generator.Ctx.ctxDepthStep <= i)
                    {
                        throw new Source.Exception($"Value named '{name}' not found in row context");
                    }
                    src = PrevValsRef;
                    ndx = new ConstExpr(i);
                }
                return(new IndexExpr(src, ndx));
            }
예제 #20
0
파일: EzInfixor.cs 프로젝트: vawser/ESDLang
            public static Expr BytecodeToInfix(EzSembleContext context, byte[] Bytes)
            {
                var bigEndianReverseBytes = Bytes.Reverse().ToArray();

                Stack <Expr> exprs = new Stack <Expr>();

                List <Expr> popArgs(int amount)
                {
                    List <Expr> args = new List <Expr>();

                    for (int i = 0; i < amount; i++)
                    {
                        args.Add(exprs.Pop());
                    }
                    args.Reverse();
                    return(args);
                }

                for (int i = 0; i < Bytes.Length; i++)
                {
                    var b = Bytes[i];
                    if (b >= 0 && b <= 0x7F)
                    {
                        exprs.Push(new ConstExpr {
                            Value = (sbyte)(b - 64)
                        });
                    }
                    else if (b == 0xA5)
                    {
                        int j = 0;
                        while (Bytes[i + j + 1] != 0 || Bytes[i + j + 2] != 0)
                        {
                            j += 2;
                        }
                        string text = context.IsBigEndian ?
                                      Encoding.BigEndianUnicode.GetString(Bytes, i + 1, j)
                            : Encoding.Unicode.GetString(Bytes, i + 1, j);

                        if (text.Contains('"') || text.Contains('\r') || text.Contains('\n'))
                        {
                            throw new Exception("Illegal character in string literal");
                        }
                        exprs.Push(new ConstExpr {
                            Value = text
                        });
                        i += j + 2;
                    }
                    else if (b == 0x80)
                    {
                        float val;
                        if (!context.IsBigEndian)
                        {
                            val = BitConverter.ToSingle(Bytes, i + 1);
                        }
                        else
                        {
                            val = BitConverter.ToSingle(bigEndianReverseBytes, (bigEndianReverseBytes.Length - 1) - (i + 1) - 4);
                        }
                        exprs.Push(new ConstExpr {
                            Value = val
                        });

                        i += 4;
                    }
                    else if (b == 0x81)
                    {
                        double val;
                        if (!context.IsBigEndian)
                        {
                            val = BitConverter.ToDouble(Bytes, i + 1);
                        }
                        else
                        {
                            val = BitConverter.ToDouble(bigEndianReverseBytes, (bigEndianReverseBytes.Length - 1) - (i + 1) - 8);
                        }
                        exprs.Push(new ConstExpr {
                            Value = val
                        });

                        i += 8;
                    }
                    else if (b == 0x82)
                    {
                        int val;
                        if (!context.IsBigEndian)
                        {
                            val = BitConverter.ToInt32(Bytes, i + 1);
                        }
                        else
                        {
                            val = BitConverter.ToInt32(bigEndianReverseBytes, (bigEndianReverseBytes.Length - 1) - (i + 1) - 4);
                        }
                        exprs.Push(new ConstExpr {
                            Value = val
                        });

                        i += 4;
                    }
                    else if (b == 0x84)
                    {
                        exprs.Push(new FunctionCall {
                            Args = popArgs(0), Name = context.GetFunctionInfo(exprs.Pop().AsInt()).Name
                        });
                    }
                    else if (b == 0x85)
                    {
                        exprs.Push(new FunctionCall {
                            Args = popArgs(1), Name = context.GetFunctionInfo(exprs.Pop().AsInt()).Name
                        });
                    }
                    else if (b == 0x86)
                    {
                        exprs.Push(new FunctionCall {
                            Args = popArgs(2), Name = context.GetFunctionInfo(exprs.Pop().AsInt()).Name
                        });
                    }
                    else if (b == 0x87)
                    {
                        exprs.Push(new FunctionCall {
                            Args = popArgs(3), Name = context.GetFunctionInfo(exprs.Pop().AsInt()).Name
                        });
                    }
                    else if (b == 0x88)
                    {
                        exprs.Push(new FunctionCall {
                            Args = popArgs(4), Name = context.GetFunctionInfo(exprs.Pop().AsInt()).Name
                        });
                    }
                    else if (b == 0x89)
                    {
                        exprs.Push(new FunctionCall {
                            Args = popArgs(5), Name = context.GetFunctionInfo(exprs.Pop().AsInt()).Name
                        });
                    }
                    else if (b == 0x8A)
                    {
                        exprs.Push(new FunctionCall {
                            Args = popArgs(6), Name = context.GetFunctionInfo(exprs.Pop().AsInt()).Name
                        });
                    }
                    else if (OperatorsByByte.ContainsKey(b))
                    {
                        if (OperatorsByByte[b] == "N")
                        {
                            exprs.Push(new UnaryExpr {
                                Op = "N", Arg = exprs.Pop()
                            });
                        }
                        else
                        {
                            exprs.Push(new BinaryExpr {
                                Op = OperatorsByByte[b], Rhs = exprs.Pop(), Lhs = exprs.Pop()
                            });
                        }
                    }
                    else if (b == 0xA6)
                    {
                        Expr top = exprs.Peek();
                        top.IfFalse = FalseCond.CONTINUE;
                    }
                    else if (b >= 0xA7 && b <= 0xAE)
                    {
                        byte regIndex = (byte)(b - 0xA7);
                        exprs.Push(new FunctionCall {
                            Args = popArgs(1), Name = $"SetREG{regIndex}"
                        });
                    }
                    else if (b >= 0xAF && b <= 0xB6)
                    {
                        byte regIndex = (byte)(b - 0xAF);
                        exprs.Push(new FunctionCall {
                            Args = popArgs(0), Name = $"GetREG{regIndex}"
                        });
                    }
                    else if (b == 0xB7)
                    {
                        Expr top = exprs.Peek();
                        top.IfFalse = FalseCond.ABORT;
                    }
                    else if (b == 0xB8)
                    {
                        // exprs.Push(new FunctionCall { Args = popArgs(1), Name = "StateGroupArg" });
                        FunctionCall func = new FunctionCall {
                            Args = popArgs(1), Name = "StateGroupArg"
                        };
                        ConstExpr ce = func.Args[0] as ConstExpr;
                        // Console.WriteLine($"{ce} {ce.Value.GetType()}");
                        exprs.Push(func);
                    }
                    else if (b == 0xB9)
                    {
                        exprs.Push(new CallResult());
                    }
                    else if (b == 0xBA)
                    {
                        // This opcode just returns a constant value 0x7FFFFFFF
                        // But use higher-level representation of it
                        exprs.Push(new CallOngoing());
                    }
                    else if (b == 0xA1)
                    {
                        //break;
                    }
                    else
                    {
                        exprs.Push(new Unknown {
                            Opcode = b
                        });
                    }
                }
                if (exprs.Count != 1)
                {
                    throw new Exception("Could not parse expr. Remaining stack: " + string.Join("; ", exprs) + $"; = {string.Join(" ", Bytes.Select(x => x.ToString("X2")))}");
                }
                return(exprs.Pop());
            }
예제 #21
0
            private Metadata(IEnumerable <NE> exprsHdr, IEnumerable <NE> exprsRow, IEnumerable <NE> exprsRes, Generator.Ctx parentCtx)
            {
                var sb = new StringBuilder();

                FixSheetExpr = Expr.RecursiveModifier(FixSheetImpl);
                FixRowExpr   = Expr.RecursiveModifier(FixRowImpl);

                #region generate header code
                ctxHdr = new Generator.Ctx(parentCtx);
                ctxHdr.CreateValue(HdrCellsRef.name, Generator.LazyDummy);
                ctxHdr.CreateValue(PrevValsRef.name, Generator.LazyDummy);

                foreach (var p in exprsHdr)
                {
                    FCurrName = p.name;
                    var expr = FixSheetExpr(p.expr);
                    var val  = Generator.Generate(expr, ctxHdr);
                    ctxHdr.CreateValue(p.name, val);
                    if (OPs.KindOf(val) == ValueKind.Const)
                    {
                        expr = new ConstExpr(val);
                    }
                    sb.AppendLine($"{p.name} = {expr}");
                }
                sb.AppendLine();

                RequiredInHdr(sSourceKey);
                RequiredInHdr(sSourceName);
                RequiredInHdr(sCondition);
                RequiredInHdr(sFirstDataRowNum);

                {
                    if (ctxHdr.name2ndx.TryGetValue(sFileContentKind, out int i))
                    {
                        FileContentKind = Convert.ToString(ctxHdr.GetConstant(sFileContentKind));
                    }
                    else
                    {
                        FileContentKind = "XLSX";
                    }
                }
                {
                    if (ctxHdr.name2ndx.TryGetValue(sFileNameExtension, out int i))
                    {
                        var val = ctxHdr.GetConstant(sFileNameExtension);
                        FileNameExtension = Utils.AsIList(val).Cast <object>().Select(Convert.ToString).ToArray();
                    }
                    else
                    {
                        FileNameExtension = new string[] { "xls", "xlsx", "xlsm" }
                    };
                }
                #endregion

                #region generate row code
                ctxRow = new Generator.Ctx(ctxHdr);
                ctxRow.CreateValue(sDataKey, Generator.LazyDummy);         // [0] - iKey
                ctxRow.CreateValue(sDataSubkey, Generator.LazyDummy);      // [1] - iSubkey
                ctxRow.CreateValue(CellValsRef.name, Generator.LazyDummy); // [2] - iRowVals

                foreach (var p in exprsRow)
                {
                    string name;
                    if (p.name.StartsWith("~"))
                    {
                        // calculated name
                        name = OPs.TryAsString(Parser.ParseToExpr(p.name.Substring(1)), ctxHdr) ?? p.name;
                    }
                    else
                    {
                        name = p.name;
                    }
                    FCurrName = name;
                    int i    = ctxRow.GetOrCreateIndexOf(name);
                    var expr = FixRowExpr(p.expr);
                    var val  = Generator.Generate(expr, ctxRow);
                    ctxRow.values[i] = val;
                    if (OPs.KindOf(val) == ValueKind.Const)
                    {
                        expr = new ConstExpr(val);
                    }
                    sb.AppendLine($"{name} = {expr}");
                }

                RequiredInRow(sDataKey);
                RequiredInRow(sDataSubkey);

                ctxRow.values[iRowVals] = null;
                ctxRow.CheckUndefinedValues();

                #endregion

                #region generate res code
                if (exprsRes != null)
                {
                    // copy all code from row to res
                    ctxRes = new Generator.Ctx(ctxHdr);
                    foreach (var p in ctxRow.name2ndx.OrderBy(p => p.Value))
                    {
                        ctxRes.values[ctxRes.CreateValue(p.Key)] = ctxRow.values[p.Value];
                    }

                    foreach (var p in exprsRes)
                    {
                        string name;
                        if (p.name.StartsWith("~"))
                        {
                            // calculated name
                            name = OPs.TryAsString(Parser.ParseToExpr(p.name.Substring(1)), ctxHdr) ?? p.name;
                        }
                        else
                        {
                            name = p.name;
                        }
                        FCurrName = name;
                        int i    = ctxRes.GetOrCreateIndexOf(name);
                        var expr = FixRowExpr(p.expr);
                        var val  = Generator.Generate(expr, ctxRes);
                        ctxRes.values[i] = val;
                        if (OPs.KindOf(val) == ValueKind.Const)
                        {
                            expr = new ConstExpr(val);
                        }
                    }
                    ctxRes.values[iRowVals] = null;
                    ctxRes.CheckUndefinedValues();
                }
                #endregion

                ctxHdr[HdrCellsRef.name] = null;
                ctxHdr[PrevValsRef.name] = null;
                ctxHdr.CheckUndefinedValues();

                FCodeText = sb.ToString();

                if (iHdrMinUsedRow > iHdrMaxUsedRow)
                {
                    iHdrMinUsedRow = iHdrMaxUsedRow;
                }
            }
예제 #22
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);
        }
예제 #23
0
파일: AST.cs 프로젝트: thefifthmatt/ESDLang
 public bool Equals(ConstExpr o) => Value.Equals(o.Value);