Ejemplo n.º 1
0
        public object Calculate(QNode typedNode, object prev = null)
        {
            if (typedNode == null)
            {
                return(null);
            }

            var s    = typedNode.AsString();
            var type = typedNode.C(0).P("type").QValue().AsString();

            switch (type)
            {
            case "s-literal":
                return(s);
            }

            try
            {
                if (s == "::query")
                {
                    var r = Calculate(typedNode.C(1));
                    foreach (var child in typedNode.Nodes().Skip(2))
                    {
                        if (r is Exception)
                        {
                            return(r);
                        }
                        r = Calculate(child, r);
                    }
                    return(r);
                }

                var functions = new Dictionary <string, Func <object, object> >
                {
                    //{"int",  o => ConvertHlp.ToInt(o)},
                    //{"to-int",  o => ConvertHlp.ToInt(o)},
                    //{"делитель",  o => Делитель(o as int?)},
                    //{"кратный",  o => Кратный(o as int?)},
                    //{"n-значный", o => N_Значный(o as int?) },
                    //{"кроме", o => Кроме(o as int?) },
                    { "true", o => true },
                    { "false", o => false },
                    { "enumerate", o => ((Set <int>)o).EnumerateNumbers() },
                    { "число", o => o },
                    { "sum", o => ((IEnumerable <int>)o).OrEmpty().Sum() },
                };

                var f = functions.Find(s);
                if (f != null)
                {
                    var v = Calculate(typedNode.C(1));
                    if (v is Exception)
                    {
                        return(v);
                    }
                    return(f(v));
                }

                var functions2 = new Dictionary <string, Func <object, object, object> >
                {
                    //{"is?",  (o1, o2) => ((Set<int>)o2).Is((int)o1)},
                    { "частное", (o1, o2) => { var v2 = o2 as int?; if (v2 == 0)
                                               {
                                                   return(new DivideByZeroException());
                                               }
                                               return(o1.As <int?>() / v2); } },
                    //{"делитель",  o => Делитель(o as int?)},
                };

                var f2 = functions2.Find(s);
                if (f2 != null)
                {
                    var v  = Calculate(typedNode.C(1));
                    var v2 = Calculate(typedNode.C(2));
                    if (v is Exception)
                    {
                        return(v);
                    }
                    if (v2 is Exception)
                    {
                        return(v2);
                    }
                    return(f2(v, v2));
                }

                var functions_s = new Dictionary <string, Func <IEnumerable <object>, object> >
                {
                    { "collection", objs => objs.OrEmpty().Select(obj => (int)obj) },
                    { "and", sets => sets.Select(set => (Set <int>)set).And() }
                };
                var fs = functions_s.Find(s);
                if (fs != null)
                {
                    var vs    = typedNode.Nodes().Skip(1).Select(n => Calculate(n)).ToArray();
                    var error = vs.OfType <Exception>().FirstOrDefault();
                    if (error != null)
                    {
                        return(error);
                    }
                    return(fs(vs));
                }

                var f_objs = FunctionIndex.Find(s);
                if (f_objs != null)
                {
                    var vs    = typedNode.Nodes().Skip(1).Select(n => Calculate(n)).ToArray();
                    var error = vs.OfType <Exception>().FirstOrDefault();
                    if (error != null)
                    {
                        return(error);
                    }
                    var fn = f_objs[0];
                    if (f_objs.Length > 1)
                    {
                        var interType = typedNode.P_("meta", "inter-type", "*").AsString();
                        fn = f_objs.FirstOrDefault(_f => _f.Args.FirstOrDefault() == interType) ?? f_objs[0];
                    }

                    return(fn.F(prev != null ? Enumerable.Repeat(prev, 1).Concat(vs).ToArray(): vs));
                }


                switch (s)
                {
                case "point":
                {
                    if (typedNode.P_("eq", 1).AsString() == "skip")
                    {
                        return(typedNode.P_("eq", 1));
                    }
                    var eqNode = typedNode.P("eq").FirstOrDefault();
                    var result = Calculate(eqNode);
                    if (result is Exception)
                    {
                        return(result);
                    }
                    return(q.Q(result, Calculate(eqNode.C(1)), Calculate(eqNode.C(2))));

                    //var taskNode = typedNode.P("task").FirstOrDefault().C(1);
                    //var expectedNode = typedNode.P("expected").FirstOrDefault().C(1);
                    //if (expectedNode.AsString() == "skip")
                    //  return q.Q("skip", expectedNode, taskNode);
                    //var task = Calculate(taskNode);
                    //var expected = Calculate(expectedNode);
                    //if (task is Exception)
                    //  return task;
                    //if (expected is Exception)
                    //  return expected;
                    //return q.Q(object.Equals(expected, task), expected, task);
                    //return q.Q(typedNode.P("id").FirstOrDefault().C(1).RawValue(),
                    //  q.Q("result", object.Equals(expected, task)),
                    //  q.Q("expected", expected),
                    //  q.Q("actual", task)
                    //);
                    //return new Exception(string.Format("{0} - {1,5}: {2}, {3}", typedNode.P("id").FirstOrDefault().C(1).AsString(), , expected, task));
                }
                }



                return(new Exception($"{s}<{type}>"));
            }
            catch (Exception exc)
            {
                return(new Exception($"{s}<{type}>", exc));
            }
        }