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