コード例 #1
0
ファイル: SolvingFunctions.cs プロジェクト: tmteam/NFun
        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);
                }
            }
        }
コード例 #2
0
ファイル: SolvingFunctions.cs プロジェクト: tmteam/NFun
        /// <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);
        }
コード例 #3
0
        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);
        }
コード例 #4
0
ファイル: SolvingFunctions.cs プロジェクト: tmteam/NFun
        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);
                }
            }
        }
コード例 #5
0
ファイル: NodeToposort2.cs プロジェクト: tmteam/NFun
        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
        }
コード例 #6
0
ファイル: SolvingFunctions.cs プロジェクト: tmteam/NFun
        /// <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);
        }
コード例 #7
0
ファイル: SolvingFunctions.cs プロジェクト: tmteam/NFun
            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);
            }
コード例 #8
0
ファイル: TicNode.cs プロジェクト: tmteam/NFun
 public void SetAncestor(int index, TicNode node)
 {
     if (node == this)
     {
         throw new ImpossibleException("CircularAncestor");
     }
     _ancestors[index] = node;
 }
コード例 #9
0
ファイル: TicNode.cs プロジェクト: tmteam/NFun
        public void AddAncestor(TicNode node)
        {
            if (node == this)
            {
                throw new ImpossibleException("CircularAncestor");
            }

            _ancestors.Add(node);
        }
コード例 #10
0
ファイル: NodeToposort.cs プロジェクト: tmteam/NFun
        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);
        }
コード例 #11
0
ファイル: SolvingFunctions.cs プロジェクト: tmteam/NFun
        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);
            }
        }
コード例 #12
0
ファイル: SolvingFunctions.cs プロジェクト: tmteam/NFun
        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);
            }
        }
コード例 #13
0
ファイル: SolvingFunctions.cs プロジェクト: tmteam/NFun
 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);
     }
 }
コード例 #14
0
ファイル: SolvingFunctions.cs プロジェクト: tmteam/NFun
            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;
            }
コード例 #15
0
ファイル: SolvingFunctions.cs プロジェクト: tmteam/NFun
        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));
        }
コード例 #16
0
ファイル: SolvingFunctions.cs プロジェクト: tmteam/NFun
        /// <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);
        }
コード例 #17
0
        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);
        }
コード例 #18
0
ファイル: NodeToposort2.cs プロジェクト: tmteam/NFun
        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);
            }
        }
コード例 #19
0
ファイル: SolvingFunctions.cs プロジェクト: tmteam/NFun
 private static void ThrowIfRecursiveTypeDefenition(TicNode node)
 {
     ThrowIfStateHasRecursiveTypeDefeinitionReq(node.State, 1);
コード例 #20
0
ファイル: NodeToposort2.cs プロジェクト: tmteam/NFun
 private void ThrowRecursiveTypeDefenition(TicNode node)
 {
     _cycle.Push(node);
     throw TicErrors.RecursiveTypeDefinition(_cycle.ToArray());
 }
コード例 #21
0
ファイル: NodeToposort2.cs プロジェクト: tmteam/NFun
        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);
        }
コード例 #22
0
ファイル: TicNode.cs プロジェクト: tmteam/NFun
 public void RemoveAncestor(TicNode node) =>
 _ancestors.Remove(node);