Ejemplo n.º 1
0
        public void Execute(DfirRoot dfirRoot, CompileCancellationToken cancellationToken)
        {
            var lifetimeGraphTree = dfirRoot.GetLifetimeGraphTree();
            BoundedLifetimeLiveVariableSet boundedLifetimeLiveVariableSet;

            while (_lifetimeVariableAssociation.TryGetBoundedLifetimeWithLiveVariables(out boundedLifetimeLiveVariableSet))
            {
                if (lifetimeGraphTree.IsDiagramLifetimeOfAnyLifetimeGraph(boundedLifetimeLiveVariableSet.Lifetime))
                {
                    // Since we assume there are no semantic errors at this point, just mark any remaining live variables
                    // in a diagram lifetime as consumed.
                    boundedLifetimeLiveVariableSet.LiveVariables.Select(l => l.Variable).ForEach(_lifetimeVariableAssociation.MarkVariableConsumed);
                    continue;
                }

                int inputVariableCount = boundedLifetimeLiveVariableSet.LiveVariables.Count();
                IEnumerable <VariableReference> interruptedVariables = _lifetimeVariableAssociation.GetVariablesInterruptedByLifetime(boundedLifetimeLiveVariableSet.Lifetime);
                int outputVariableCount = interruptedVariables.Count();

                Diagram startSearch = boundedLifetimeLiveVariableSet.LiveVariables.First().Terminal.ParentDiagram;
                LifetimeGraphIdentifier originGraphIdentifier = lifetimeGraphTree.GetBoundedLifetimeGraphIdentifier(boundedLifetimeLiveVariableSet.Lifetime);
                Diagram originDiagram = originGraphIdentifier.FindDiagramForGraphIdentifier(startSearch);

                LiveVariable[] liveVariables = boundedLifetimeLiveVariableSet.LiveVariables.ToArray();
                for (int i = 0; i < liveVariables.Length; ++i)
                {
                    LiveVariable liveVariable = liveVariables[i];
                    while (liveVariable.Terminal.ParentDiagram != originDiagram)
                    {
                        liveVariable = PullLiveVariableUpToNextHigherDiagram(liveVariable);
                    }
                    liveVariables[i] = liveVariable;
                }

                TerminateLifetimeNode terminateLifetime = TerminateLifetimeNodeHelpers.CreateTerminateLifetimeWithFacades(originDiagram, inputVariableCount, outputVariableCount);
                int inputIndex = 0;
                foreach (LiveVariable liveVariable in liveVariables)
                {
                    // TODO: maybe assert that liveVariable.Terminal is unwired here?
                    Terminal terminateLifetimeInputTerminal = terminateLifetime.InputTerminals[inputIndex];
                    Wire.Create(originDiagram, liveVariable.Terminal, terminateLifetimeInputTerminal);
                    terminateLifetimeInputTerminal.GetFacadeVariable().MergeInto(liveVariable.Variable);
                    _lifetimeVariableAssociation.MarkVariableConsumed(liveVariable.Variable);

                    ++inputIndex;
                }
                int outputIndex = 0;
                foreach (VariableReference interruptedVariable in interruptedVariables)
                {
                    Terminal terminateLifetimeOutputTerminal = terminateLifetime.OutputTerminals[outputIndex];
                    terminateLifetimeOutputTerminal.GetFacadeVariable().MergeInto(interruptedVariable);
                    _lifetimeVariableAssociation.MarkVariableLive(interruptedVariable, terminateLifetimeOutputTerminal);

                    ++outputIndex;
                }
            }
        }
        public void CreateBorrowAndTerminateLifetimeNodes(LifetimeVariableAssociation lifetimeVariableAssociation)
        {
            if (_borrowRequired)
            {
                Node                 parentNode         = _facades.First().Terminal.ParentNode;
                BorrowMode           borrowMode         = _mutableBorrow ? BorrowMode.Mutable : BorrowMode.Immutable;
                int                  borrowInputCount   = _facades.Count;
                Diagram              inputParentDiagram = _facades.First().Terminal.ParentDiagram;
                var                  explicitBorrow     = new ExplicitBorrowNode(inputParentDiagram, borrowMode, borrowInputCount, true, false);
                AutoBorrowNodeFacade borrowNodeFacade   = AutoBorrowNodeFacade.GetNodeFacade(explicitBorrow);
                foreach (var terminal in explicitBorrow.Terminals)
                {
                    borrowNodeFacade[terminal] = new SimpleTerminalFacade(terminal, default(TypeVariableReference));
                }

                int index = 0;
                foreach (var facade in _facades)
                {
                    Terminal          input = facade.Terminal;
                    VariableReference ownerVariable = input.GetFacadeVariable(), borrowVariable;
                    ((AutoborrowingInputTerminalFacade)facade).AddPostBorrowCoercion(ref input, out borrowVariable);
                    InsertBorrowAheadOfTerminal(input, explicitBorrow, index, ownerVariable, borrowVariable);
                    ++index;
                }

                List <TerminateLifetimeOutputTerminalFacade> terminates = new List <TerminateLifetimeOutputTerminalFacade>();
                foreach (var terminal in parentNode.OutputTerminals)
                {
                    var terminateFacade = _nodeFacade[terminal] as TerminateLifetimeOutputTerminalFacade;
                    if (terminateFacade != null && _facades.Contains(terminateFacade.InputFacade))
                    {
                        terminates.Add(terminateFacade);
                    }
                }

                if (terminates.Count == borrowInputCount)
                {
                    Diagram outputParentDiagram = terminates.First().Terminal.ParentDiagram;
                    var     terminateLifetime   = TerminateLifetimeNodeHelpers.CreateTerminateLifetimeWithFacades(outputParentDiagram, borrowInputCount, borrowInputCount);

                    index = 0;
                    foreach (var terminate in terminates)
                    {
                        InsertTerminateLifetimeBehindTerminal(terminate.Terminal, terminateLifetime, index, lifetimeVariableAssociation);
                        ++index;
                    }
                }
                else if (terminates.Count > 0)
                {
                    throw new InvalidOperationException("Mismatched terminates and borrows; not sure what to do");
                }
            }
        }