Exemplo n.º 1
0
        private IngoingEdgesOverlay ComputeIngoingEdges(BuildGraph graph)
        {
            var ingoing = new IngoingEdgesOverlay(() => new List <EdgeInfo>());

            var visited = new OrdinalOverlay <BuildNodeId, BuildNode, bool>();

            var stack = new Stack <BuildNode>();

            stack.Push(graph.EnterNode);
            visited[graph.EnterNode] = true;

            while (stack.Count > 0)
            {
                var node = stack.Pop();

                foreach (var edge in node.OutgoingEdges)
                {
                    var edgeInfo = new EdgeInfo(edge, node);
                    ingoing[edge.To].Add(edgeInfo);

                    if (!visited[edge.To])
                    {
                        stack.Push(edge.To);
                        visited[edge.To] = true;
                    }
                }
            }

            return(ingoing);
        }
Exemplo n.º 2
0
        // TODO: Consider splitting into multiple methods to increase readability
        public GeneratedGraphs Translate()
        {
            this.builder      = new FlowGraphBuilder(this.flowGraphId);
            this.ingoingEdges = this.ComputeIngoingEdges(this.BuildGraph);

            this.expressionTranslator    = new ExpressionTranslator(this);
            this.buildToFlowVariablesMap = new OrdinalOverlay <BuildVariableId, BuildVariable, FlowVariable>();
            this.buildToFlowNodesMap     = new OrdinalOverlay <BuildNodeId, BuildNode, FlowNodeMappedInfo>();
            var nodeQueue    = new Queue <BuildNode>();
            var edgeQueue    = new Queue <EdgeInfo>();
            var visitedNodes = new OrdinalOverlay <BuildNodeId, BuildNode, bool>();

            var buildParameters = this.BuildGraph.Variables
                                  .Where(v => v.Origin == VariableOrigin.Parameter || v.Origin == VariableOrigin.This);
            var flowParameters = new List <FlowVariable>();

            foreach (var parameter in buildParameters)
            {
                flowParameters.Add(this.TranslateVariable(parameter));
            }

            var flowEnterNode = this.builder.AddEnterNode(flowParameters);

            this.buildToFlowNodesMap[this.BuildGraph.EnterNode] = flowEnterNode;
            visitedNodes[this.BuildGraph.EnterNode]             = true;

            Contract.Assert(this.BuildGraph.EnterNode.OutgoingEdges.Count == 1);
            var firstNonEnterNode = this.BuildGraph.EnterNode.OutgoingEdges.Single().To;

            nodeQueue.Enqueue(firstNonEnterNode);
            visitedNodes[firstNonEnterNode] = true;

            while (nodeQueue.Count > 0)
            {
                var buildNode = nodeQueue.Dequeue();
                Contract.Assert(visitedNodes[buildNode]);
                Contract.Assert(this.buildToFlowNodesMap[buildNode].FlowNode == null);

                BuildNode firstBuildNode, lastBuildNode;

                var flowNode = this.TryTranslateBorderNode(buildNode);
                if (flowNode != null)
                {
                    firstBuildNode = buildNode;
                    lastBuildNode  = buildNode;

                    this.buildToFlowNodesMap[buildNode] = flowNode;
                }
                else
                {
                    this.ProcessInnerNodesSequence(buildNode, out firstBuildNode, out lastBuildNode, out var operations);
                    flowNode = this.builder.AddInnerNode(operations, lastBuildNode.Flags);      // TODO: Handle flag merging when there are flag types that need it
                    this.MapAssignmentsToFlowNode(firstBuildNode, lastBuildNode, flowNode);
                }

                // TODO: Try to get rid of the empty nodes (empty blocks etc.)
                Contract.Assert(flowNode != null);

                foreach (var edge in lastBuildNode.OutgoingEdges)
                {
                    if (!visitedNodes[edge.To])
                    {
                        nodeQueue.Enqueue(edge.To);
                        visitedNodes[edge.To] = true;
                    }
                }

                foreach (var edgeInfo in this.ingoingEdges[firstBuildNode])
                {
                    var flowFromNode = this.buildToFlowNodesMap[edgeInfo.From].FlowNode;
                    if (flowFromNode == null)
                    {
                        edgeQueue.Enqueue(edgeInfo);
                    }
                    else
                    {
                        this.TranslateEdge(edgeInfo.Edge, edgeInfo.From, flowFromNode, flowNode);
                    }
                }
            }

            while (edgeQueue.Count > 0)
            {
                var      edgeInfo = edgeQueue.Dequeue();
                FlowNode flowFrom = this.buildToFlowNodesMap[edgeInfo.From];
                FlowNode flowTo   = this.buildToFlowNodesMap[edgeInfo.Edge.To];

                Contract.Assert(flowFrom != null);
                Contract.Assert(flowTo != null);
                this.TranslateEdge(edgeInfo.Edge, edgeInfo.From, flowFrom, flowTo);
            }

            this.FlowGraph = this.builder.FreezeAndReleaseGraph();

            this.FinishDisplayGraph();

            return(new GeneratedGraphs(this.FlowGraph, this.DisplayGraph));
        }