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