internal static void EnsureSyncedDependencyStability(TopoSort <LocalMod> synced, TopoSort <LocalMod> full) { var errored = new HashSet <LocalMod>(); var errorLog = new StringBuilder(); foreach (var mod in synced.list) { var chains = new List <List <LocalMod> >(); //define recursive chain finding method Action <LocalMod, Stack <LocalMod> > FindChains = null; FindChains = (search, stack) => { stack.Push(search); if (search.properties.side == ModSide.Both && stack.Count > 1) { if (stack.Count > 2) //direct Both -> Both references are ignored { chains.Add(stack.Reverse().ToList()); } } else //recursively build the chain, all entries in stack should be unsynced { foreach (var dep in full.Dependencies(search)) { FindChains(dep, stack); } } stack.Pop(); }; FindChains(mod, new Stack <LocalMod>()); if (chains.Count == 0) { continue; } var syncedDependencies = synced.AllDependencies(mod); foreach (var chain in chains) { if (!syncedDependencies.Contains(chain.Last())) { errored.Add(mod); errorLog.AppendLine(mod + " indirectly depends on " + chain.Last() + " via " + string.Join(" -> ", chain)); } } } if (errored.Count > 0) { errorLog.AppendLine("Some of these mods may not exist on both client and server. Add a direct sort entries or weak references."); throw new ModSortingException(errored, errorLog.ToString()); } }
public void EstablishNodeSet(Dictionary <string, Record> recordMapOfNodes) { NodeSet ns = scanFeeder.GetNodeSet(); ns.SetDependencyMatrix(scanFeeder.CreateDependencyMatrix()); List <Node> sortedList = TopoSort.DfsTopoSort(ns.GetNodeMap(), ns.GetNodeIdMap(), ns.GetDependencyMatrix().GetDependencyMatrixArray(), recordMapOfNodes); if (sortedList.Count != 0) { ns.SetNodeSortedList(sortedList); } else { scanFeeder.HandleWarning("RuleSet needs rewriting due to it is cyclic."); } }
/// <summary> /// Iterative topological sorting of expressions (ability of calculated values names is taked into account) /// </summary> /// <param name="srcItems"></param> /// <param name="parentCtx"></param> /// <returns></returns> public static IEnumerable <Expr> DoSort2(IEnumerable <Expr> srcItems, Generator.Ctx parentCtx) { var items = new List <Expr>(srcItems); var mh = new ModifyHelper(); var allLets = new Dictionary <string, Expr>(); while (true) { mh.ctx = new Generator.Ctx(parentCtx); mh.ctx.CreateValue(FuncDefs_Core.stateTryGetConst, string.Empty); for (int i = 0; i < items.Count; i++) { var item = items[i]; item = mh.modify(item); items[i] = item; foreach (var letName in mh.lets) { allLets[letName] = item; //mh.ctx.CreateValue(letName); } mh.lets.Clear(); } { var values = mh.ctx.values; var lets = new List <Expr>(); foreach (var p in mh.ctx.name2ndx) { if (p.Value == 0) { continue; } var v = values[p.Value]; if (v == null || allLets.ContainsKey(p.Key) || OPs.KindOf(v) != ValueKind.Const) { continue; } var le = CallExpr.let(new ReferenceExpr(p.Key), new ConstExpr(v)); allLets.Add(p.Key, le); lets.Add(le); } if (lets.Count > 0) { items.InsertRange(0, lets); } } if (!mh.thereIsNameResolve && !mh.thereIsNonresolved) { break; } mh.thereIsNonresolved = mh.thereIsNameResolve = false; items = TopoSort.DoSort(items, e => EnumRefs(e) .Where(s => s != null && allLets.ContainsKey(s)) .Select(s => allLets[s]) ); allLets.Clear(); } return(items); }
/// <summary> /// Iterative topological sorting of expressions (ability of calculated values names is taked into account) /// </summary> /// <param name="srcItems"></param> /// <param name="parentCtx"></param> /// <returns></returns> public static IEnumerable <Expr> DoSort(IEnumerable <Expr> srcItems, Generator.Ctx parentCtx) { List <ItemInfo> infos = srcItems.Select(item => new ItemInfo(item)).ToList(); while (true) { //****** sort items with defined names var allLets = new Dictionary <string, ItemInfo>(); foreach (var nfo in infos) { foreach (var name in nfo.lets.Keys) { allLets[name] = nfo; } } infos = TopoSort.DoSort(infos, ii => ii.refs.Keys.Where(s => allLets.ContainsKey(s)).Select(s => allLets[s])); var thereIsNameResolve = false; var allNamesRosolved = true; var ctx = new Generator.Ctx(parentCtx); //****** calculate unresolved names for (int i = 0; i < infos.Count; i++) { var nfo = infos[i]; // side effect?: new values can be declared in context var value = TryGen(ctx, nfo.expr); var lets2 = nfo.lets2; for (int j = 0; j < lets2.Count;) { var let2 = lets2[j]; var letName = TryGen(ctx, let2); if (letName != Fail && OPs.KindOf(letName) == ValueKind.Const) { thereIsNameResolve = true; lets2.RemoveAt(j); nfo.lets[Convert.ToString(letName)] = true; } else { j++; allNamesRosolved = false; } } var refs2 = nfo.refs2; for (int j = 0; j < refs2.Count;) { var ref2 = refs2[j]; var refName = TryGen(ctx, ref2); if (refName != Fail && OPs.KindOf(refName) == ValueKind.Const) { thereIsNameResolve = true; refs2.RemoveAt(j); nfo.refs[Convert.ToString(refName)] = true; } else { j++; allNamesRosolved = false; } } if (nfo.refs.Keys.Any(s => ctx.IndexOf(s) < 0)) { allNamesRosolved = false; } } if (allNamesRosolved || !thereIsNameResolve) { break; } } return(infos.Select(ii => ii.expr)); }
public NodeSet CreateIterateNodeSet(NodeSet parentNodeSet) { DependencyMatrix parentDM = parentNodeSet.GetDependencyMatrix(); Dictionary <string, Node> parentNodeMap = parentNodeSet.GetNodeMap(); Dictionary <int?, string> parentNodeIdMap = parentNodeSet.GetNodeIdMap(); Dictionary <string, Node> thisNodeMap = new Dictionary <string, Node>(); Dictionary <int?, string> thisNodeIdMap = new Dictionary <int?, string>(); List <Dependency> tempDependencyList = new List <Dependency>(); NodeSet newNodeSet = new NodeSet(); thisNodeMap.Add(this.nodeName, this); thisNodeIdMap.Add(this.nodeId, this.nodeName); Enumerable.Range(1, this.givenListSize).ToList().ForEach((nth) => { parentDM.GetToChildDependencyList(this.nodeId).ForEach((item) => { if (this.GetNodeId() + 1 != item) // not first question id { Node tempChildNode = parentNodeMap[parentNodeIdMap[item]]; LineType lineType = tempChildNode.GetLineType(); Node tempNode = null; string nextNThInString = Oridinal(nth); if (lineType.Equals(LineType.VALUE_CONCLUSION)) { tempNode = new ValueConclusionLine(nextNThInString + " " + this.GetVariableName() + " " + tempChildNode.GetNodeName(), tempChildNode.GetTokens()); } else if (lineType.Equals(LineType.COMPARISON)) { tempNode = new ComparisonLine(nextNThInString + " " + this.GetVariableName() + " " + tempChildNode.GetNodeName(), tempChildNode.GetTokens()); FactValue tempNodeFv = ((ComparisonLine)tempNode).GetRHS(); if (tempNodeFv.GetFactValueType().Equals(FactValueType.STRING)) { FactValue tempFv = FactValue.Parse(nextNThInString + " " + this.GetVariableName() + " " + FactValue.GetValueInString(FactValueType.STRING, tempNodeFv)); tempNode.SetValue(tempFv); } } else if (lineType.Equals(LineType.EXPR_CONCLUSION)) { tempNode = new ExprConclusionLine(nextNThInString + " " + this.GetVariableName() + " " + tempChildNode.GetNodeName(), tempChildNode.GetTokens()); } thisNodeMap.Add(tempNode.GetNodeName(), tempNode); thisNodeIdMap.Add(tempNode.GetNodeId(), tempNode.GetNodeName()); tempDependencyList.Add(new Dependency(this, tempNode, parentDM.GetDependencyType(this.nodeId, item))); CreateIterateNodeSetAux(parentDM, parentNodeMap, parentNodeIdMap, thisNodeMap, thisNodeIdMap, tempDependencyList, item, tempNode.GetNodeId(), nextNThInString); } else // first question id { Node firstIterateQuestionNode = parentNodeSet.GetNodeByNodeId(parentNodeSet.GetDependencyMatrix().GetToChildDependencyList(this.GetNodeId()).Min()); if (!thisNodeMap.ContainsKey(firstIterateQuestionNode.GetNodeName())) { thisNodeMap.Add(firstIterateQuestionNode.GetNodeName(), firstIterateQuestionNode); thisNodeIdMap.Add(item, firstIterateQuestionNode.GetNodeName()); tempDependencyList.Add(new Dependency(this, firstIterateQuestionNode, parentDM.GetDependencyType(this.nodeId, item))); } } }); }); int numberOfRules = Node.GetStaticNodeId(); int[,] dependencyMatrix = new int[numberOfRules, numberOfRules]; tempDependencyList.ForEach(dp => { int parentId = dp.GetParentNode().GetNodeId(); int childId = dp.GetChildNode().GetNodeId(); int dpType = dp.GetDependencyType(); dependencyMatrix[parentId, childId] = dpType; }); newNodeSet.SetNodeIdMap(thisNodeIdMap); newNodeSet.SetNodeMap(thisNodeMap); newNodeSet.SetDependencyMatrix(new DependencyMatrix(dependencyMatrix)); newNodeSet.SetFactMap(parentNodeSet.GetFactMap()); newNodeSet.SetNodeSortedList(TopoSort.DfsTopoSort(thisNodeMap, thisNodeIdMap, dependencyMatrix)); // newNodeSet.getNodeSortedList().stream().forEachOrdered(item->System.out.println(item.getNodeId()+"="+item.getNodeName())); return(newNodeSet); }
public static string DumpDeps(Generator.Ctx parentCtx, Dictionary <string, XlsxR.Sheet> sheets, string[] stringTable, string[] forCells) { var sb = new StringBuilder(); foreach (var sheetCells in forCells.Select(SheetAndCell).GroupBy(sc => sc.Sheet)) { var sheetKey = (sheetCells.Key == null) ? sheets.Keys.First() : sheetCells.Key; var hlp = new DepsHelper() { already = new Dictionary <string, bool>(), sheet = sheets[sheetKey], stringTable = stringTable, parentCtx = parentCtx, }; foreach (var r in hlp.sheet.vals.Keys) { if (hlp.maxNdxColVal < r.col) { hlp.maxNdxColVal = r.col; } if (hlp.maxNdxRowVal < r.row) { hlp.maxNdxRowVal = r.row; } } var deps = new List <(CellRange cell, Expr expr)>(); foreach (var sc in sheetCells) { deps.AddRange(hlp.DumpDepsImpl(sc.Cell)); } deps.Sort((a, b) => CellRange.Compare(a.cell, b.cell)); var dict = deps.ToDictionary(d => d.cell.name, d => d.expr); var sorted = TopoSort.DoSort( deps.Select(d => d.cell.name), cell => dict[cell].EnumerateReferences() ); if (sb.Length > 0) { sb.AppendLine(); } sb.AppendLine($"//********** sheet: {sheetKey}"); foreach (var cell in sorted) { var info = hlp.GetCode(CellRange.FromName(cell), dict[cell]); if (!string.IsNullOrEmpty(info.rowComm)) { sb.AppendLine($"//row: {info.rowComm}"); } if (!string.IsNullOrEmpty(info.colComm)) { sb.AppendLine($"//col: {info.colComm}"); } sb.AppendLine(info.rngExpr); } } return(sb.ToString()); }