Пример #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);
        }
Пример #2
0
        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);
            }
        }
Пример #3
0
        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);
            }
        }
Пример #4
0
            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;
            }
Пример #5
0
        /// <summary>
        /// Merge all node states. First non ref state (or first state) called 'main'
        /// 'main' state takes all constrains and ancestors
        ///
        /// All other nodes refs to 'main'
        ///
        /// Returns 'main'
        /// </summary>
        public static TicNode MergeGroup(IEnumerable <TicNode> cycleRoute)
        {
            var main = cycleRoute.FirstOrDefault(c => !(c.State is StateRefTo))
                       ?? cycleRoute.First();

            foreach (var current in cycleRoute)
            {
                if (current == main)
                {
                    continue;
                }

                if (current.State is StateRefTo refState)
                {
                    if (!cycleRoute.Contains(refState.Node))
                    {
                        throw new InvalidOperationException();
                    }
                }
                else
                {
                    //merge main and current
                    main.State = GetMergedStateOrNull(main.State, current.State)
                                 ?? throw TicErrors.CannotMergeGroup(cycleRoute.ToArray(), main, current);
                }

                main.AddAncestors(current.Ancestors.Where(c => c != main));
                current.ClearAncestors();

                if (!current.IsSolved)
                {
                    current.State = new StateRefTo(main);
                }
            }

            var newAncestors = main.Ancestors
                               .Where(r => !cycleRoute.Contains(r))
                               .Distinct()
                               .ToList();

            main.ClearAncestors();
            main.AddAncestors(newAncestors);
            return(main);
        }
Пример #6
0
 private void ThrowRecursiveTypeDefenition(TicNode node)
 {
     _cycle.Push(node);
     throw TicErrors.RecursiveTypeDefinition(_cycle.ToArray());
 }