Пример #1
0
        public static IEnumerable <T> Browse <T>(QNode node, Func <QNode, T> f)
        {
            var r = f(node);

            return(Enumerable.Repeat(r, ((object)r != null) ? 1 : 0)
                   .Concat(node.Nodes().Skip(1).SelectMany(child => Browse(child, f))));
        }
Пример #2
0
        public static QNode Transform(QNode node, Func <QNode, Func <QNode, QNode>, QNode> f)
        {
            if (node == null)
            {
                return(null);
            }
            var r = f(node, n => Transform(n, f));

            if (r != null && r != node)
            {
                return(r);
            }
            List <QNode> childs = null;
            var          nodes  = node.Nodes();

            //for (var i = 1; i < nodes.Length; ++i)
            foreach (var pair in nodes.Select((n, i) => new { child = n, i }).Skip(1))
            {
                var child = pair.child;

                var r_child = Transform(child, f);
                if (r_child != null && r_child != child && childs == null)
                {
                    childs = new List <QNode>(nodes.Take(pair.i));
                }
                childs?.Add(r_child ?? child);
            }
            if (childs != null)
            {
                return(new QNode(node.RawValue(), childs.ToArray()));
            }
            return(node);
        }
Пример #3
0
 public static QNode W(this QNode q, params object[] content)
 {
     if (q == null)
     {
         return(null);
     }
     return(new QNode(q.RawValue(), q.Nodes().Concat(content.Select(item => item is QNode ? (QNode)item : new QNode(item))).ToArray()));
 }
Пример #4
0
        public static QNode Normalizator5_Lift(QNode typedNode, Func <QNode, QNode> normalize)
        {
            var s = typedNode.AsString();

            switch (s)
            {
            case "eq":
            case "and":
            case "sum":
            case "min":
            case "max":
            case "count":
            case "is?":
            case "take":
            {
                var interTypes = typedNode.P_s(0, "inter-type", "*").OrEmpty().Select(interType => interType.AsString()).ToArray();

                var childs = typedNode.Nodes().Skip(1)
                             .Select((child, i) =>
                    {
                        var interType = interTypes.ElementAtOrDefault(i) ?? interTypes.FirstOrDefault();
                        var type      = child.P_(0, "type", "*").AsString();
                        return(new { child, nchild = Lift(interType, type, normalize(child) ?? child) });
                    });
                if (childs.Any(pair => pair.child != pair.nchild))
                {
                    return(q.Q(typedNode.RawValue(), typedNode.C(0), childs.Select(pair => pair.nchild)));
                }
            }
            break;
                //case "::query":
                //    {
                //        var childs = typedNode.Nodes.Skip(1);
                //        var prev = childs.FirstOrDefault();
                //        List<QNode> nchilds = null;
                //        foreach (var pair in childs.Select((c, i) => new { child = c, i }))
                //        {
                //            var child = pair.child;

                //            var sourceType = prev.P_(0, "type", "*").AsString();
                //            var targetType = child.AsString() == "take" ? "int-s" : null;
                //            var nchild = Lift(targetType, sourceType, normalize(prev));
                //            if (nchild != child && childs == null)
                //            {
                //                nchilds = new List<QNode>(typedNode.Nodes.Take(pair.i + 1));
                //            }

                //            if (nchilds != null)
                //                nchilds.Add(nchild);
                //        }
                //        if (nchilds != null)
                //            return q.Q(typedNode.Value, nchilds);
                //    }
                //    break;
            }
            return(typedNode);
        }
Пример #5
0
        static HElement View(QNode node, IDictionary <Guid, QCalculator.Function> functionIndex)
        {
            var functionId = ConvertHlp.ToGuid(node.C(0).P_("function-id", "*").AsString());
            var f          = functionId.Maybe(_ => functionIndex.Find(functionId.Value));

            return(h.Div
                   (
                       h.@class("q"),
                       h.Span(h.@class("q-type"), $" ({TypeToString(node.C(0).P("type").QValue().FirstOrDefault())}) "),
                       h.Span(node.RawValue()),
                       h.Span(h.@class("q-inter-type"), $" ({node.P_s(0, "inter-type", "*").Select(interType => TypeToString(interType)).JoinToString(", ")}) "),
                       functionId.Maybe(_ => h.A(h.style("font-size:75%"), h.href($"#f-{_}"), "f-" + f?.Index, h.title(FunctionFullName(f.RawDescription)))),
                       node.Nodes().OrEmpty().Skip(1).Select(n => View(n, functionIndex))
                   ));
        }
Пример #6
0
        public static QNode Normalizator3(QNode typedNode, Func <QNode, QNode> normalize)
        {
            var s = typedNode.AsString();

            switch (s)
            {
            case "not":
            {
                var childType = typedNode.C(1).C(0).P("type").QValue().AsString();
                if (childType != null)
                {
                    return(q.Q(typedNode.RawValue(), MetaType(childType, interType: childType), typedNode.C_s(1).OrEmpty().Select(child => normalize(child) ?? child)));
                }
            }
            break;

            case "::query":
            {
                var childType = typedNode.Nodes().LastOrDefault().C(0).P("type").QValue().AsString();
                if (childType != null)
                {
                    return(q.Q(typedNode.RawValue(), MetaType(childType, interType: childType), typedNode.C_s(1).OrEmpty().Select(child => normalize(child) ?? child)));
                }
            }
            break;

            case "and":
            {
                var childs = typedNode.C_s(1).OrEmpty().Select(child => normalize(child) ?? child).ToArray();
                if (childs.All(n => Is("set", n.C(0).P("type").QValue().AsString())))
                {
                    return(q.Q(typedNode.RawValue(), MetaType("set", interType: "set"), childs));
                }
            }
            break;
            }
            return(null);
        }
Пример #7
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));
            }
        }
Пример #8
0
        public QNode Identify(QNode typedNode, Func <QNode, QNode> normalize)
        {
            var s         = typedNode.AsString();
            var interType = typedNode.C(0).P_("inter-type", "*").AsString();
            var f         = FunctionIndex.Find(s).OrEmpty().FirstOrDefault(_f => _f.Args.FirstOrDefault() == interType);

            if (f != null)
            {
                return(q.Q(typedNode.RawValue(), typedNode.C(0).W(q.Q("function-id", f.Id)), typedNode.Nodes().Skip(1).Select(child => normalize(child))));
            }
            return(typedNode);
        }
Пример #9
0
        public static QNode Typified(QNode node, Dictionary <string, QNode[]> functionIndex)
        {
            var    type      = "-";
            string childType = null;
            string interType = null;

            string[] interTypes = null;

            var   s      = node.AsString();
            QNode prefix = null;

            switch (s)
            {
            case "id":
                return(q.Q(s, MetaType("id", interType: "s-literal"), q.Q(node.QValue().RawValue(), MetaType("s-literal", interType: "void"))));

            case "делитель":
            case "кратный":
            case "кроме":
            case "n-значный":
            case "четный":
            case "нечетный":
            case ">":
            case "<":
            case "больше":
            case "меньше":
                type      = "set";
                childType = "int";
                interType = "int";
                break;

            case "is?":
                return(q.Q(s, q.Q("meta", q.Q("type", "bool"), q.Q("inter-type", "int", q.Q("set", "int"))), node.Nodes().Select(child => Typified(child, functionIndex))));

            case "true":
            case "false":
                type      = "bool";
                interType = "void";
                break;

            case "частное":    //TODO synonym div
            case "add":
            case "subtract":
            case "div":
            case "mul":
                type      = "number";
                interType = "number";
                break;

            case "mod":
            case "idiv":
                type      = "int";
                interType = "int";
                break;

            case "sum":
            case "count":
            case "min":
            case "max":
                type      = "int";
                interType = "int-s";
                break;

            case "число":
                type = "number";
                break;

            case "enumerate":
                type      = "int-s";
                interType = "set";
                break;

            case "take":
                type       = "int-s";
                interTypes = new[] { "int-s", "int" };
                break;

            default:
            {
                var functions = functionIndex.Find(s);
                if (functions.OrEmpty().Any())
                {
                    var function = functions[0];
                    type      = function.P_("result", "type", "*").AsString();
                    childType = function.P_("result", "type", "*", "*").AsString();
                    interType = function.P_("arg", 0, "type", "*").AsString();
                }
                else if (!string.IsNullOrEmpty(s) && char.IsDigit(s[0]) && s.All(ch => char.IsDigit(ch) || ch == '-' || ch == '.' || ch == ','))
                {
                    type      = "s-literal";
                    interType = "void";
                    var numberType = s.Any(ch => ch == ',' || ch == '.') ? "number" : "int";
                    prefix = q.Q("to-" + numberType, MetaType(numberType, interType: "s-literal"));
                }
                else
                {
                    var structureTypes = new[] { "point", "task", "expected", "skip" };
                    if (structureTypes.Contains(s))
                    {
                        type = s;
                        if (s == "point")
                        {
                            interType = "structure";
                        }
                        if (s == "skip")
                        {
                            interType = "s-literal";
                        }
                    }
                }
            }
            break;
            }


            var    v = node.RawValue();
            object n = MetaType(type, childType, interType: interType, interTypes: interTypes);

            var childs = node.Nodes().Select(child => Typified(child, functionIndex)).ToArray();
            var res    = q.Q(v, n, childs);

            if (prefix != null)
            {
                return(prefix.W(res));
            }
            return(res);
        }
Пример #10
0
        public static QNode Normalizator4(QNode typedNode, Func <QNode, QNode> normalize)
        {
            var s = typedNode.AsString();

            switch (s)
            {
            case "eq":
            {
                var childType  = typedNode.C(1).C(0).P("type").QValue().AsString();
                var childType2 = typedNode.C(2).C(0).P("type").QValue().AsString();
                if (childType == "int" && childType2 == "number")
                {
                    childType = "number";
                }
                if (childType == "int" && childType2 == "set")
                {
                    childType = "int-s";
                }
                if (childType == "int" && childType2 == "int-s")
                {
                    childType = "int-s";
                }
                if (childType == "int-s" && childType2 == "int")
                {
                    childType = "int-s";
                }
                return(q.Q(typedNode.RawValue(), MetaType("bool", interType: childType), typedNode.Nodes().Skip(1).Select(child => normalize(child) ?? child)));
            }
            }
            return(typedNode);
        }
Пример #11
0
        public static QNode Normalizator(QNode typedNode, Func <QNode, QNode> normalize)
        {
            var s = typedNode.AsString();

            switch (s)
            {
            case "число":
                return(normalize(typedNode.C(1)) ?? typedNode.C(1));

            case "skip":
                return(q.Q(typedNode.RawValue(),
                           typedNode.C(0),
                           typedNode.C(1).Maybe(reasonNode =>
                                                q.Q(reasonNode.RawValue(),
                                                    MetaType("s-literal", interType: "void"),
                                                    reasonNode.Nodes().OrEmpty().Skip(1)
                                                    )
                                                )
                           ));

            case "point":
            {
                var pointNode = q.Q(typedNode.RawValue(),
                                    typedNode.C(0),
                                    typedNode.C(1).Maybe(taskNode => taskNode.AsString() == "id" ? normalize(taskNode) ?? taskNode : q.Q("id", MetaType("id"), normalize(taskNode) ?? taskNode)),
                                    typedNode.C(2).Maybe(taskNode => taskNode.AsString() == "task" ? normalize(taskNode) ?? taskNode : q.Q("task", MetaType("task"), normalize(taskNode) ?? taskNode)),
                                    typedNode.C(3).Maybe(expectedNode => expectedNode.AsString() == "expected" ? normalize(expectedNode) ?? expectedNode : q.Q("expected", MetaType("expected"), normalize(expectedNode) ?? expectedNode))
                                    );
                return(q.Q(pointNode.RawValue(),
                           pointNode.C(0),
                           pointNode.C(1),
                           q.Q("eq", MetaType("bool"), ToCollection_IfNeed(pointNode.C(3).QValue()), ToCollection_IfNeed(pointNode.C(2).QValue()))
                           ));
            }

            case "::query":
            {
                var childs = typedNode.Nodes.Skip(1);
                var result = childs.Skip(1).Aggregate(childs.FirstOrDefault(), (current, child) => q.Q(child.Value, child.Nodes.FirstOrDefault(), current, child.Nodes().Skip(1)));
                return(normalize(result));
            }

            default:
            {
                var childs = typedNode.Nodes().Skip(1).ToArray();
                //if (!new[] { "point", "skip", "is?", "and", "частное" }.Contains(s) && childs.Length > 1)
                if (new[] { "from" }.Contains(s) && childs.Length > 1)
                {
                    var childType = childs[0].C(0).P("type").QValue().AsString();
                    if (!childType.IsNullOrEmpty() && childType != "-")
                    {
                        if (childs.Skip(1).All(child => child.C(0).P("type").QValue().AsString() == childType))
                        {
                            if (!childType.EndsWith("-s"))        //TODO поддержать коллекции коллекций и смешение одиночек и коллекций
                            {
                                return(q.Q(typedNode.RawValue(), typedNode.C(0), q.Q("collection", MetaType(childType + "-s", interType: childType), childs)));
                            }
                        }
                    }
                }
            }
            break;
            }
            return(typedNode);
        }