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 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 string Error(QNode typedNode) { var type = typedNode.C(0).P("type").QValue().AsString(); if (type == "-") { return($"Не задан тип '{type}' для '{typedNode.AsString()}'"); } if (!typedNode.C(0).P("inter-type").QValue().Any()) { return($"Не задан inter-type для '{typedNode.AsString()}'"); } return(null); }
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 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); }
public static QNode Normalizator2(QNode typedNode, Func <QNode, QNode> normalize) { var s = typedNode.AsString(); switch (s) { case "choose": { if (typedNode.C(1).AsString() == "from" && typedNode.C(2).AsString() == "condition" && typedNode.C(1).Nodes().Count() <= 2 && typedNode.C(2).Nodes().Count() <= 2) { return(q.Q("and", MetaType("-"), normalize(typedNode.C(1).C(1)) ?? typedNode.C(1).C(1), normalize(typedNode.C(2).C(1)) ?? typedNode.C(2).C(1))); } } break; } return(null); }
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 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); }