Exemple #1
0
        /// <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);
        }