private static void PushConstraintsRecursive(TicNode node) { if (node.State is ICompositeState composite) { foreach (var member in composite.Members) { PushConstraintsRecursive(member); } } // micro optimization. node.Ancestors.ToArray() is very expensive operation // but cases of 0 or 1 ancestors are most common var ancSize = node.Ancestors.Count; if (ancSize == 1) { PushConstraints(node, node.Ancestors[0]); } else if (ancSize > 0) { // We have to use ToArray() option, since some node ancestors can be removed // during the operation foreach (var ancestor in node.Ancestors.ToArray()) { PushConstraints(node, ancestor); } } }
/// <summary> /// Merge two nodes. Both of them become equiualent. /// /// In complex situation, 'secondary' node becomes reference to 'main' node, if it is possible /// </summary> public static void MergeInplace(TicNode main, TicNode secondary) { if (main == secondary) { return; } if (main.State is StateRefTo) { var nonreferenceMain = main.GetNonReference(); var nonreferenceSecondary = secondary.GetNonReference(); MergeInplace(nonreferenceMain, nonreferenceSecondary); return; } if (secondary.GetNonReference() == main) { return; } var res = GetMergedStateOrNull(main.State, secondary.State); if (res == null) { throw TicErrors.CannotMerge(main, secondary); } main.State = res; if (res is ITypeState t && t.IsSolved) { secondary.State = res; return; } main.AddAncestors(secondary.Ancestors.Where(a => a != main)); secondary.ClearAncestors(); secondary.State = new StateRefTo(main); }
private TicNode GetNonReferenceNodeOrNull(TicNode node) { if (node.VisitMark == _nodeInListMark) { return(node); } if (!(node.State is StateRefTo refTo)) { return(node); } if (node.VisitMark == RefVisitingMark) { return(null); } node.VisitMark = RefVisitingMark; var res = GetNonReferenceNodeOrNull(refTo.Node); if (res == null) { _refRoute.Push(node); } else { node.VisitMark = -1; //merge if (node.Ancestors.Any()) { res.AddAncestors(node.Ancestors); node.ClearAncestors(); } } return(res); }
private static void DestructionRecursive(TicNode node) { ThrowIfRecursiveTypeDefenition(node); if (node.State is ICompositeState composite) { if (composite.HasAnyReferenceMember) { node.State = composite.GetNonReferenced(); } foreach (var member in composite.Members) { DestructionRecursive(member); } } // micro optimization. node.Ancestors.ToArray() is very expensive operation // but cases of 0 or 1 ancestors are most common var ancSize = node.Ancestors.Count; if (ancSize == 1) { Destruction(node, node.Ancestors[0]); } else if (ancSize > 0) { // We have to use ToArray() option, since some node ancestors can be removed // during the operation foreach (var ancestor in node.Ancestors.ToArray()) { Destruction(node, ancestor); } } }
private bool VisitNodeInCycle(TicNode node) { node.VisitMark = NotVisited; _cycle.Push(node); if (_cycleInitiator != node) { //continue to collect cycle route return(false); } // Ref and/or ancestor cycle found // That means all elements in cycle have to be merged // (a<= b <= c = a) => (a = b = c) var merged = SolvingFunctions.MergeGroup(_cycle.Reverse()); // Cycle is merged _cycle = null; _cycleInitiator = null; // continue toposort algorithm return(Visit(merged)); // Whole cycle is not found yet // step back }
/// <summary> /// Transform constrains state to array state /// </summary> public static StateArray TransformToArrayOrNull(object descNodeName, ConstrainsState descendant) { if (descendant.NoConstrains) { var constrains = new ConstrainsState(); var eName = "e" + descNodeName.ToString().ToLower() + "'"; var node = TicNode.CreateTypeVariableNode(eName, constrains); return(new StateArray(node)); } else if (descendant.HasDescendant && descendant.Descedant is StateArray arrayEDesc) { if (arrayEDesc.Element is StateRefTo) { var origin = arrayEDesc.ElementNode.GetNonReference(); if (origin.IsSolved) { return(new StateArray(origin)); } } else if (arrayEDesc.ElementNode.IsSolved) { return(arrayEDesc); } } return(null); }
static bool FindRecursionTypeRoute(TicNode node, HashSet <TicNode> nodes) { if (!nodes.Add(node)) { return(true); } if (node.State is StateRefTo r) { return(FindRecursionTypeRoute(r.Node, nodes)); } if (node.State is ICompositeState composite) { foreach (var compositeMember in composite.Members) { if (FindRecursionTypeRoute(compositeMember, nodes)) { return(true); } } } nodes.Remove(node); return(false); }
public void SetAncestor(int index, TicNode node) { if (node == this) { throw new ImpossibleException("CircularAncestor"); } _ancestors[index] = node; }
public void AddAncestor(TicNode node) { if (node == this) { throw new ImpossibleException("CircularAncestor"); } _ancestors.Add(node); }
public bool AddToTopology(TicNode node) { if (node == null) { return(true); } if (node.VisitMark == IsVisited) { // if node is already visited then skip it return(true); } if (node.VisitMark == InProcess) { // Node is visiting, that means cycle found // initialize cycle collecting process _cycle = new Stack <TicNode>(_path.Count + 1); _cycleInitiator = node; return(false); } node.VisitMark = InProcess; if (node.State is StateRefTo refTo) { _refenceNodesCount++; if (!AddToTopology(refTo.Node)) { // VisitNodeInCycle rolls back graph // so we need to decrement counter _refenceNodesCount--; // this node is part of cycle return(VisitNodeInCycle(node)); } } else if (node.State is ICompositeState composite) { foreach (var member in composite.Members) { if (!AddToTopology(member)) { ThrowRecursiveTypeDefenition(node); } } } foreach (var ancestor in node.Ancestors) { if (!AddToTopology(ancestor)) { return(VisitNodeInCycle(node)); } } _path.Push(node); node.VisitMark = IsVisited; return(true); }
public static void PushConstraints(TicNode descendant, TicNode ancestor) { if (descendant == ancestor) { return; } if (!ancestor.State.ApplyDescendant(PushConstraintsFunctions.Singletone, ancestor, descendant)) { throw TicErrors.IncompatibleNodes(ancestor, descendant); } }
private static void PullConstrains(TicNode descendant, TicNode ancestor) { if (descendant == ancestor) { return; } var res = ancestor.State.ApplyDescendant(PullConstraintsFunctions.SingleTone, ancestor, descendant); if (!res) { throw TicErrors.IncompatibleTypes(ancestor, descendant); } }
public static void BecomeReferenceFor(this TicNode referencedNode, TicNode original) { referencedNode = referencedNode.GetNonReference(); original = original.GetNonReference(); if (referencedNode.Type == TicNodeType.SyntaxNode) { MergeInplace(original, referencedNode); } else { MergeInplace(referencedNode, original); } }
static void ThrowIfNodeHasRecursiveTypeDefenitionReq(TicNode node, int bypassNumber) { if (node.VisitMark == bypassNumber) { var route = new HashSet <TicNode>(); FindRecursionTypeRoute(node, route); throw TicErrors.RecursiveTypeDefinition(route.ToArray()); } var markBefore = node.VisitMark; node.VisitMark = bypassNumber; ThrowIfStateHasRecursiveTypeDefeinitionReq(node.State, bypassNumber); node.VisitMark = markBefore; }
public static bool Destruction(TicNode descendantNode, TicNode ancestorNode) { var nonRefAncestor = ancestorNode.GetNonReference(); var nonRefDescendant = descendantNode.GetNonReference(); if (nonRefDescendant == nonRefAncestor) { return(true); } return(nonRefAncestor.State.ApplyDescendant( DestructionFunctions.Singletone, nonRefAncestor, nonRefDescendant)); }
/// <summary> /// Transform constrains to fun state /// </summary> public static StateFun TransformToFunOrNull(object descNodeName, ConstrainsState descendant, StateFun ancestor) { if (descendant.NoConstrains) { var argNodes = new TicNode[ancestor.ArgsCount]; for (int i = 0; i < ancestor.ArgsCount; i++) { var argNode = TicNode.CreateTypeVariableNode("a'" + descNodeName + "'" + i, new ConstrainsState()); argNode.AddAncestor(ancestor.ArgNodes[i]); argNodes[i] = argNode; } var retNode = TicNode.CreateTypeVariableNode("r'" + descNodeName, new ConstrainsState()); retNode.AddAncestor(ancestor.RetNode); return(StateFun.Of(argNodes, retNode)); } if (descendant.Descedant is StateFun funDesc && funDesc.ArgsCount == ancestor.ArgsCount) { if (funDesc.IsSolved) { return(funDesc); } // For perfomance bool allArgsAreSolved = true; var nrArgNodes = new TicNode[funDesc.ArgNodes.Length]; for (int i = 0; i < funDesc.ArgNodes.Length; i++) { nrArgNodes[i] = funDesc.ArgNodes[i].GetNonReference(); allArgsAreSolved = allArgsAreSolved && nrArgNodes[i].IsSolved; } var nrRetNode = funDesc.RetNode.GetNonReference(); if (allArgsAreSolved && nrRetNode.IsSolved) { return(StateFun.Of(nrArgNodes, nrRetNode)); } } return(null); }
public TicNode GetNonReferenceMergedOrNull(TicNode node) { if (node.VisitMark == RefVisitedMark) { return(null); } _refRoute = new Stack <TicNode>(); var nonReference = GetNonReferenceNodeOrNull(node); if (nonReference != null) { return(nonReference); } // ref cycle found! // the node becomes one non reference node with no constrains node.State = new ConstrainsState(); foreach (var refNode in _refRoute) { if (refNode == node) { continue; } if (refNode.VisitMark == RefVisitedMark) { continue; } node.AddAncestors(refNode.Ancestors); refNode.ClearAncestors(); refNode.VisitMark = RefVisitedMark; if (refNode.IsMemberOfAnything) { refNode.IsMemberOfAnything = false; } } return(node); }
public void AddToTopology(TicNode node) { if (node == null) { return; } if (node.VisitMark == NodeInListMark) { return; } var nonReference = _searchNonReferenceAlgorithm.GetNonReferenceMergedOrNull(node); if (nonReference != null && nonReference.VisitMark != NodeInListMark) { nonReference.VisitMark = NodeInListMark; if (nonReference.State is StateRefTo) { throw new ImpossibleException($"Toposort adds reference node to list: {node}"); } _allNodes.Add(nonReference); } }
private static void ThrowIfRecursiveTypeDefenition(TicNode node) { ThrowIfStateHasRecursiveTypeDefeinitionReq(node.State, 1);
private void ThrowRecursiveTypeDefenition(TicNode node) { _cycle.Push(node); throw TicErrors.RecursiveTypeDefinition(_cycle.ToArray()); }
private bool Visit(TicNode node) { _visitDepth++; if (_visitDepth > 1000) { throw new InvalidOperationException($"Toposort stack overflow. Node: {node}"); } if (node == null) { return(true); } if (node.VisitMark == IsVisited) { // if node is already visited then skip it return(true); } if (node.VisitMark == InProcess) { // Node is visiting, that means cycle found // initialize cycle collecting process _cycle = new Stack <TicNode>(_path.Count + 1); _cycleInitiator = node; return(false); } node.VisitMark = InProcess; if (node.State is StateRefTo refTo) { _refenceNodesCount++; if (!Visit(refTo.Node)) { // VisitNodeInCycle rolls back graph // so we need to decrement counter _refenceNodesCount--; // this node is part of cycle return(VisitNodeInCycle(node)); } } else if (node.State is ICompositeState composite) { foreach (var member in composite.Members) { if (!Visit(member)) { ThrowRecursiveTypeDefenition(node); } } } for (var i = 0; i < node.Ancestors.Count; i++) { var ancestor = node.Ancestors[i]; if (!Visit(ancestor)) { return(VisitNodeInCycle(node)); } } _path.Push(node); node.VisitMark = IsVisited; return(true); }
public void RemoveAncestor(TicNode node) => _ancestors.Remove(node);