Example #1
0
        private static void CreateFacadesForInoutReferenceParameter(
            TypeVariableSet typeVariableSet,
            AutoBorrowNodeFacade nodeFacade,
            NIType parameterDataType,
            Terminal inputTerminal,
            Terminal outputTerminal,
            Dictionary <NIType, TypeVariableReference> genericTypeParameters,
            Dictionary <NIType, ReferenceInputTerminalLifetimeGroup> lifetimeFacadeGroups,
            Dictionary <NIType, LifetimeTypeVariableGroup> lifetimeVariableGroups)
        {
            NIType lifetimeType = parameterDataType.GetReferenceLifetimeType();
            bool   isMutable    = parameterDataType.IsMutableReferenceType();
            InputReferenceMutability mutability = parameterDataType.GetInputReferenceMutabilityFromType();
            var lifetimeGroup = lifetimeVariableGroups[lifetimeType];
            ReferenceInputTerminalLifetimeGroup facadeGroup;

            if (!lifetimeFacadeGroups.TryGetValue(lifetimeType, out facadeGroup))
            {
                facadeGroup = nodeFacade.CreateInputLifetimeGroup(mutability, lifetimeGroup.LazyNewLifetime, lifetimeGroup.LifetimeType);
            }
            // TODO: should not add outputTerminal here if borrow cannot be auto-terminated
            // i.e., if there are in-only or out-only parameters that share lifetimeType
            TypeVariableReference referentTypeVariableReference   = typeVariableSet.CreateTypeVariableReferenceFromNIType(parameterDataType.GetReferentType(), genericTypeParameters);
            TypeVariableReference mutabilityTypeVariableReference = mutability == InputReferenceMutability.Polymorphic
                ? genericTypeParameters[parameterDataType.GetReferenceMutabilityType()]
                : default(TypeVariableReference);

            facadeGroup.AddTerminalFacade(inputTerminal, referentTypeVariableReference, mutabilityTypeVariableReference, outputTerminal);
        }
        internal static void CreateTunnelNodeFacade(Tunnel tunnel)
        {
            AutoBorrowNodeFacade nodeFacade      = AutoBorrowNodeFacade.GetNodeFacade(tunnel);
            TypeVariableSet      typeVariableSet = tunnel.DfirRoot.GetTypeVariableSet();

            TypeVariableReference typeVariable;

            bool executesConditionally = tunnel.ParentStructure.DoesStructureExecuteConditionally();

            if (executesConditionally && tunnel.Direction == Direction.Output)
            {
                Terminal valueInput  = tunnel.InputTerminals.ElementAt(0),
                         valueOutput = tunnel.OutputTerminals.ElementAt(0);

                typeVariable            = typeVariableSet.CreateReferenceToNewTypeVariable();
                nodeFacade[valueOutput] = new SimpleTerminalFacade(valueOutput, typeVariable);
                nodeFacade[valueInput]  = new TunnelTerminalFacade(valueInput, nodeFacade[valueOutput]);
            }
            else
            {
                List <Constraint> constraints = new List <Constraint>();
                if (tunnel.Direction == Direction.Output)
                {
                    // TODO: for multi-diagram structures, each diagram should share a lifetime related to the entire structure
                    LifetimeGraphIdentifier parentLifetimeGraph = tunnel.InputTerminals[0].ParentDiagram.GetLifetimeGraphIdentifier();
                    constraints.Add(new OutlastsLifetimeGraphConstraint(parentLifetimeGraph));
                }
                typeVariable = typeVariableSet.CreateReferenceToNewTypeVariable(constraints);
                foreach (Terminal terminal in tunnel.Terminals)
                {
                    nodeFacade[terminal] = new SimpleTerminalFacade(terminal, typeVariable);
                }
            }
        }
            private void InsertStringToSliceAheadOfTerminal(Terminal sliceReceiver, out VariableReference stringReferenceVariable, out Terminal stringReferenceTerminal)
            {
                FunctionalNode stringToSlice                = new FunctionalNode(sliceReceiver.ParentDiagram, Signatures.StringToSliceType);
                Terminal       stringToSliceInput           = stringToSlice.InputTerminals[0],
                               stringToSliceOutput          = stringToSlice.OutputTerminals[0];
                VariableReference sliceReceiverTrueVariable = sliceReceiver.GetTrueVariable();

                TypeVariableSet       typeVariableSet = stringToSliceInput.GetTypeVariableSet();
                TypeVariableReference stringSliceReferenceType = sliceReceiverTrueVariable.TypeVariableReference;
                TypeVariableReference u, lifetime;
                bool m;

                typeVariableSet.TryDecomposeReferenceType(stringSliceReferenceType, out u, out lifetime, out m);
                TypeVariableReference stringReferenceType = typeVariableSet.CreateReferenceToReferenceType(
                    false,
                    typeVariableSet.CreateReferenceToLiteralType(PFTypes.String),
                    lifetime);

                AutoBorrowNodeFacade stringToSliceFacade = AutoBorrowNodeFacade.GetNodeFacade(stringToSlice);

                stringToSliceFacade[stringToSliceInput]  = new SimpleTerminalFacade(stringToSliceInput, stringReferenceType);
                stringToSliceFacade[stringToSliceOutput] = new SimpleTerminalFacade(stringToSliceOutput, default(TypeVariableReference));

                sliceReceiver.ConnectedTerminal.ConnectTo(stringToSliceInput);
                stringToSliceOutput.WireTogether(sliceReceiver, SourceModelIdSource.NoSourceModelId);

                stringToSliceOutput.GetFacadeVariable().MergeInto(sliceReceiverTrueVariable);
                stringReferenceVariable = stringToSliceInput.GetFacadeVariable();
                stringReferenceTerminal = stringToSliceInput;
            }
Example #4
0
        private void CreateDefaultFacadeForOutputNodeTerminal(Node outputNode, NIType outputTerminalType)
        {
            AutoBorrowNodeFacade outputNodeFacade = AutoBorrowNodeFacade.GetNodeFacade(outputNode);
            Terminal             outputTerminal   = outputNode.OutputTerminals[0];

            outputNodeFacade[outputTerminal] = new SimpleTerminalFacade(
                outputTerminal,
                outputNode.GetTypeVariableSet().CreateTypeVariableReferenceFromNIType(outputTerminalType));
        }
Example #5
0
        public static TerminateLifetimeNode CreateTerminateLifetimeWithFacades(Diagram parentDiagram, int inputs, int outputs)
        {
            var terminateLifetime = new TerminateLifetimeNode(parentDiagram, inputs, outputs);
            AutoBorrowNodeFacade terminateLifetimeFacade = AutoBorrowNodeFacade.GetNodeFacade(terminateLifetime);

            foreach (var terminal in terminateLifetime.Terminals)
            {
                terminateLifetimeFacade[terminal] = new SimpleTerminalFacade(terminal, default(TypeVariableReference));
            }
            return(terminateLifetime);
        }
 public ReferenceInputTerminalLifetimeGroup(
     AutoBorrowNodeFacade nodeFacade,
     InputReferenceMutability mutability,
     Lazy <Lifetime> lazyNewLifetime,
     TypeVariableReference lifetimeType)
 {
     _nodeFacade         = nodeFacade;
     _mutability         = mutability;
     _lazyBorrowLifetime = lazyNewLifetime;
     LifetimeType        = lifetimeType;
 }
Example #7
0
        internal static void InsertDropForVariable(Diagram parentDiagram, LiveVariable liveUnboundedLifetimeVariable, ITypeUnificationResultFactory unificationResultFactory)
        {
            var                  drop          = new DropNode(parentDiagram);
            Terminal             inputTerminal = drop.InputTerminals[0];
            AutoBorrowNodeFacade nodeFacade    = AutoBorrowNodeFacade.GetNodeFacade(drop);

            nodeFacade[inputTerminal] = new SimpleTerminalFacade(
                inputTerminal,
                parentDiagram.GetTypeVariableSet().CreateReferenceToNewTypeVariable());

            liveUnboundedLifetimeVariable.ConnectToTerminalAsInputAndUnifyVariables(inputTerminal, unificationResultFactory);
        }
        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");
                }
            }
        }
Example #9
0
        bool IDfirNodeVisitor <bool> .VisitLoopConditionTunnel(LoopConditionTunnel loopConditionTunnel)
        {
            Terminal nodeTerminal          = loopConditionTunnel.InputTerminals[0];
            var      connectedWireTerminal = nodeTerminal.ConnectedTerminal;

            if (connectedWireTerminal != null)
            {
                // Unify node input terminal with its connected source
                AutoBorrowNodeFacade nodeFacade = AutoBorrowNodeFacade.GetNodeFacade(loopConditionTunnel);
                nodeFacade[nodeTerminal].UnifyWithConnectedWireTypeAsNodeInput(connectedWireTerminal.GetFacadeVariable(), _typeUnificationResults);
            }
            OutputLifetimeInterruptsInputVariable(nodeTerminal, loopConditionTunnel.OutputTerminals[0]);
            return(true);
        }
Example #10
0
        private void ConnectOutputTerminal(Terminal outputTerminal, Terminal newOutputTerminal)
        {
            AutoBorrowNodeFacade nodeToReplaceFacade   = AutoBorrowNodeFacade.GetNodeFacade(outputTerminal.ParentNode);
            AutoBorrowNodeFacade newTerminalNodeFacade = AutoBorrowNodeFacade.GetNodeFacade(newOutputTerminal.ParentNode);

            if (outputTerminal.IsConnected)
            {
                outputTerminal.ConnectedTerminal.ConnectTo(newOutputTerminal);
                newTerminalNodeFacade[newOutputTerminal] = nodeToReplaceFacade[outputTerminal];
            }
            else
            {
                InsertDropTransform.InsertDropForVariable(newOutputTerminal.ParentDiagram, LiveVariable.FromTerminal(newOutputTerminal), _unificationResultFactory);
            }
        }
Example #11
0
        private T ConnectNewNodeToOutputTerminal <T>(Node outputTerminalOwner, Func <Diagram, T> createNode) where T : Node
        {
            var nodeToConnect = createNode(outputTerminalOwner.ParentDiagram);
            AutoBorrowNodeFacade nodeToConnectFacade = AutoBorrowNodeFacade.GetNodeFacade(nodeToConnect);
            Terminal             inputTerminal       = nodeToConnect.InputTerminals[0];

            nodeToConnectFacade[inputTerminal] = new SimpleTerminalFacade(
                inputTerminal,
                outputTerminalOwner.GetTypeVariableSet().CreateReferenceToNewTypeVariable());
            Terminal outputTerminal = outputTerminalOwner.OutputTerminals[0];

            new LiveVariable(outputTerminal.GetTrueVariable(), outputTerminal)
            .ConnectToTerminalAsInputAndUnifyVariables(inputTerminal, _unificationResultFactory);
            return(nodeToConnect);
        }
Example #12
0
        private void UnifyNodeInputTerminalTypes(Node node)
        {
            AutoBorrowNodeFacade nodeFacade = AutoBorrowNodeFacade.GetNodeFacade(node);

            foreach (var nodeTerminal in node.InputTerminals)
            {
                var connectedWireTerminal           = nodeTerminal.ConnectedTerminal;
                VariableReference unifyWithVariable = connectedWireTerminal != null
                                                      // Unify node input terminal with its connected source
                    ? connectedWireTerminal.GetFacadeVariable()
                                                      // Unify node input with immutable Void type
                    : nodeTerminal.CreateNewVariableForUnwiredTerminal();

                nodeFacade[nodeTerminal].UnifyWithConnectedWireTypeAsNodeInput(unifyWithVariable, _typeUnificationResults);
            }
        }
        private LiveVariable PullLiveVariableUpToNextHigherDiagram(LiveVariable liveVariable)
        {
            Tunnel   outputTunnel   = liveVariable.Terminal.ParentDiagram.ParentStructure.CreateTunnel(Direction.Output, TunnelMode.LastValue, NITypes.Void, NITypes.Void);
            Terminal inputTerminal  = outputTunnel.InputTerminals[0],
                     outputTerminal = outputTunnel.OutputTerminals[0];

            CreateNodeFacadesTransform.CreateTunnelNodeFacade(outputTunnel);

            Wire.Create(liveVariable.Terminal.ParentDiagram, liveVariable.Terminal, inputTerminal);
            AutoBorrowNodeFacade.GetNodeFacade(outputTunnel)[inputTerminal].UnifyWithConnectedWireTypeAsNodeInput(
                liveVariable.Variable,
                new TerminalTypeUnificationResults());
            _lifetimeVariableAssociation.MarkVariableConsumed(liveVariable.Variable);

            return(new LiveVariable(outputTerminal.GetFacadeVariable(), outputTerminal));
        }
        public void Execute(DfirRoot dfirRoot, CompileCancellationToken cancellationToken)
        {
            LiveVariable liveUnboundedLifetimeVariable;

            while (_lifetimeVariableAssociation.TryGetLiveVariableWithUnboundedLifetime(out liveUnboundedLifetimeVariable))
            {
                Diagram              parentDiagram = liveUnboundedLifetimeVariable.Terminal.ParentDiagram;
                var                  drop          = new DropNode(parentDiagram);
                Terminal             inputTerminal = drop.InputTerminals[0];
                AutoBorrowNodeFacade nodeFacade    = AutoBorrowNodeFacade.GetNodeFacade(drop);
                nodeFacade[inputTerminal] = new SimpleTerminalFacade(inputTerminal, default(TypeVariableReference));

                Wire.Create(parentDiagram, liveUnboundedLifetimeVariable.Terminal, inputTerminal);
                inputTerminal.GetFacadeVariable().MergeInto(liveUnboundedLifetimeVariable.Variable);
                _lifetimeVariableAssociation.MarkVariableConsumed(liveUnboundedLifetimeVariable.Variable);
            }
        }
Example #15
0
        public static DecomposeStructNode CreateDecomposeStructNodeWithFacades(Diagram parentDiagram, NIType structType)
        {
            var decomposeStructNode              = new DecomposeStructNode(parentDiagram, structType);
            AutoBorrowNodeFacade nodeFacade      = AutoBorrowNodeFacade.GetNodeFacade(decomposeStructNode);
            TypeVariableSet      typeVariableSet = parentDiagram.GetTypeVariableSet();

            foreach (var pair in decomposeStructNode.OutputTerminals.Zip(structType.GetFields()))
            {
                Terminal outputTerminal = pair.Key;
                NIType   elementType    = pair.Value.GetDataType();
                TypeVariableReference elementTypeVariable = typeVariableSet.CreateTypeVariableReferenceFromNIType(elementType);
                nodeFacade[outputTerminal] = new SimpleTerminalFacade(outputTerminal, elementTypeVariable);
            }

            TypeVariableReference structTypeVariable = typeVariableSet.CreateTypeVariableReferenceFromNIType(structType);
            Terminal inputTerminal = decomposeStructNode.InputTerminals[0];

            nodeFacade[inputTerminal] = new SimpleTerminalFacade(inputTerminal, structTypeVariable);
            return(decomposeStructNode);
        }
Example #16
0
        private FunctionalNode CreateInputReplacementNode(FunctionalNode toReplace, Func <Diagram, FunctionalNode> createNode)
        {
            var replacementNode = createNode(toReplace.ParentDiagram);
            AutoBorrowNodeFacade nodeToReplaceFacade = AutoBorrowNodeFacade.GetNodeFacade(toReplace);
            AutoBorrowNodeFacade replacementFacade   = AutoBorrowNodeFacade.GetNodeFacade(replacementNode);

            foreach (var terminalPair in toReplace.InputTerminals.Zip(replacementNode.InputTerminals))
            {
                Terminal toReplaceTerminal = terminalPair.Key, replacementTerminal = terminalPair.Value;
                Wire     wire = (Wire)toReplaceTerminal.ConnectedTerminal.ParentNode;
                toReplaceTerminal.ConnectedTerminal.ConnectTo(replacementTerminal);
                VariableReference sourceVariable = wire.SourceTerminal.ConnectedTerminal.GetTrueVariable();
                replacementFacade[replacementTerminal]
                .UnifyWithConnectedWireTypeAsNodeInput(sourceVariable, _unificationResultFactory);
            }
            // TODO: this doesn't work because the Wires connected to createPromiseNode's inputs may have been created during
            // automatic node insertion, and in that case do not have correct facades or variables.
            // createPromiseNode.UnifyNodeInputTerminalTypes(_unificationResultFactory);
            replacementFacade.FinalizeAutoBorrows();
            return(replacementNode);
        }
Example #17
0
        private static void CreateFacadesForDecomposeTupleNode(this DecomposeTupleNode decomposeTupleNode, TypeVariableSet typeVariableSet)
        {
            if (decomposeTupleNode.DecomposeMode == DecomposeMode.Borrow)
            {
                throw new NotSupportedException();
            }
            TypeVariableReference[] elementTypes = new TypeVariableReference[decomposeTupleNode.OutputTerminals.Count];
            AutoBorrowNodeFacade    nodeFacade   = AutoBorrowNodeFacade.GetNodeFacade(decomposeTupleNode);

            for (int i = 0; i < decomposeTupleNode.OutputTerminals.Count; ++i)
            {
                Terminal outputTerminal           = decomposeTupleNode.OutputTerminals[i];
                TypeVariableReference elementType = typeVariableSet.CreateReferenceToNewTypeVariable();
                nodeFacade[outputTerminal] = new SimpleTerminalFacade(outputTerminal, elementType);
                elementTypes[i]            = elementType;
            }

            TypeVariableReference tupleType = typeVariableSet.CreateReferenceToTupleType(elementTypes);
            Terminal inputTerminal          = decomposeTupleNode.InputTerminals[0];

            nodeFacade[inputTerminal] = new SimpleTerminalFacade(inputTerminal, tupleType);
        }
        protected override void VisitWire(Wire wire)
        {
            TypeVariableReference wireTypeVariable;
            var constraints = new List <Constraint>();

            if (wire.SinkTerminals.HasMoreThan(1))
            {
                constraints.Add(new SimpleTraitConstraint("Copy"));
            }
            wireTypeVariable = _typeVariableSet.CreateReferenceToNewTypeVariable(constraints);

            AutoBorrowNodeFacade wireFacade = AutoBorrowNodeFacade.GetNodeFacade(wire);

            foreach (var terminal in wire.Terminals)
            {
                wireFacade[terminal] = new SimpleTerminalFacade(terminal, wireTypeVariable);
            }
            Terminal sourceTerminal, firstSinkTerminal;

            if (wire.TryGetSourceTerminal(out sourceTerminal) && (firstSinkTerminal = wire.SinkTerminals.FirstOrDefault()) != null)
            {
                wireFacade[firstSinkTerminal].FacadeVariable.MergeInto(wireFacade[sourceTerminal].FacadeVariable);
            }
        }
Example #19
0
        /// <summary>
        /// Gets the true <see cref="VariableReference"/> associated with the <see cref="Terminal"/>, i.e., the reference
        /// to the variable that will be supplied directly to the terminal as input.
        /// </summary>
        /// <param name="terminal">The terminal.</param>
        /// <returns>The true <see cref="VariableReference"/>.</returns>
        public static VariableReference GetTrueVariable(this Terminal terminal)
        {
            TerminalFacade terminalFacade = AutoBorrowNodeFacade.GetNodeFacade(terminal.ParentNode)[terminal];

            return(terminalFacade?.TrueVariable ?? new VariableReference());
        }
Example #20
0
        protected override void VisitNode(Node node)
        {
            AutoBorrowNodeFacade nodeFacade = AutoBorrowNodeFacade.GetNodeFacade(node);

            nodeFacade.CreateBorrowAndTerminateLifetimeNodes(_lifetimeVariableAssociation);
        }
 bool IDfirNodeVisitor <bool> .VisitMethodCallNode(MethodCallNode methodCallNode)
 {
     AutoBorrowNodeFacade.GetNodeFacade(methodCallNode).SetLifetimeInterruptedVariables(_lifetimeVariableAssociation);
     return(true);
 }
Example #22
0
 protected override void VisitNode(Node node)
 {
     AutoBorrowNodeFacade.GetNodeFacade(node).FinalizeAutoBorrows();
 }
Example #23
0
 bool IDfirNodeVisitor <bool> .VisitFunctionalNode(FunctionalNode functionalNode)
 {
     AutoBorrowNodeFacade.GetNodeFacade(functionalNode).SetLifetimeInterruptedVariables(_lifetimeVariableAssociation);
     return(true);
 }
Example #24
0
 protected override void VisitBorderNode(BorderNode borderNode)
 {
     AutoBorrowNodeFacade.GetNodeFacade(borderNode).FinalizeAutoBorrows();
 }
Example #25
0
        private void DecomposeMethodCall(MethodCallNode methodCallNode, bool isYielding, bool mayPanic)
        {
            NIType outputType;
            // TODO: try to use something like Unit or Void
            NIType emptyOutputType = NITypes.Boolean;

            switch (methodCallNode.OutputTerminals.Count)
            {
            case 0:
                outputType = emptyOutputType;
                break;

            case 1:
                outputType = methodCallNode.OutputTerminals[0].GetTrueVariable().Type;
                break;

            default:
                outputType = methodCallNode.OutputTerminals.Select(t => t.GetTrueVariable().Type).DefineTupleType();
                break;
            }

            AutoBorrowNodeFacade methodCallNodeFacade = AutoBorrowNodeFacade.GetNodeFacade(methodCallNode);
            AwaitNode            awaitNode            = null;

            if (isYielding)
            {
                CreateMethodCallPromise createMethodCallPromise       = new CreateMethodCallPromise(methodCallNode.ParentDiagram, methodCallNode.Signature, methodCallNode.TargetName);
                AutoBorrowNodeFacade    createMethodCallPromiseFacade = AutoBorrowNodeFacade.GetNodeFacade(createMethodCallPromise);
                foreach (var terminalPair in methodCallNode.InputTerminals.Zip(createMethodCallPromise.InputTerminals))
                {
                    Terminal methodCallTerminal = terminalPair.Key, createMethodCallPromiseTerminal = terminalPair.Value;
                    methodCallTerminal.ConnectedTerminal.ConnectTo(createMethodCallPromiseTerminal);
                    createMethodCallPromiseFacade[createMethodCallPromiseTerminal] = methodCallNodeFacade[methodCallTerminal];
                }

                Terminal methodCallOutputTerminal = methodCallNode.OutputTerminals.FirstOrDefault();
                NIType   awaitOutputType          = mayPanic ? outputType.CreatePanicResult() : outputType;
                NIType   promiseType     = awaitOutputType.CreateMethodCallPromise();
                Terminal promiseTerminal = createMethodCallPromise.OutputTerminals[0];
                createMethodCallPromiseFacade[promiseTerminal] = new SimpleTerminalFacade(
                    promiseTerminal,
                    createMethodCallPromise.GetTypeVariableSet().CreateTypeVariableReferenceFromNIType(promiseType));

                awaitNode = ConnectNewNodeToOutputTerminalWithOutputFacade(createMethodCallPromise, diagram => new AwaitNode(diagram), awaitOutputType);
                VariableSet           variableSet            = awaitNode.GetVariableSet();
                TypeVariableReference outputTypeVariable     = awaitNode.OutputTerminal.GetTrueVariable().TypeVariableReference;
                TypeVariableReference pollResultTypeVariable = variableSet.TypeVariableSet.CreateReferenceToOptionType(outputTypeVariable);
                awaitNode.PollResultVariable = variableSet.CreateNewVariable(
                    diagramId: 0,
                    variableType: pollResultTypeVariable,
                    mutable: false);
            }

            Node outputNode = awaitNode;

            if (mayPanic)
            {
                Node panicOrContinueInput = awaitNode;
                if (!isYielding)
                {
                    // Create PanickingMethodCall as input to PanicOrContinue
                    throw new NotImplementedException("Calling non-yielding panicking methods not supported yet.");
                }
                outputNode = ConnectNewNodeToOutputTerminalWithOutputFacade(
                    panicOrContinueInput,
                    diagram => new PanicOrContinueNode(diagram),
                    outputType);
            }

            Terminal outputNodeTerminal = outputNode.OutputTerminals[0];

            switch (methodCallNode.OutputTerminals.Count)
            {
            case 0:
                // no method call output terminals; drop the result of the await
                InsertDropTransform.InsertDropForVariable(outputNode.ParentDiagram, LiveVariable.FromTerminal(outputNodeTerminal), _unificationResultFactory);
                break;

            case 1:
                ConnectOutputTerminal(methodCallNode.OutputTerminals[0], outputNodeTerminal);
                break;

            default:
            {
                // for >1 method call output terminals, decompose the tuple result of the await and match each
                // decomposed terminal to a method call terminal
                DecomposeTupleNode decomposeTupleNode = InsertDropTransform.InsertDecompositionForTupleVariable(
                    methodCallNode.ParentDiagram,
                    LiveVariable.FromTerminal(outputNodeTerminal),
                    _unificationResultFactory);
                foreach (var pair in methodCallNode.OutputTerminals.Zip(decomposeTupleNode.OutputTerminals))
                {
                    Terminal methodCallTerminal = pair.Key, decomposeTupleTerminal = pair.Value;
                    ConnectOutputTerminal(methodCallTerminal, decomposeTupleTerminal);
                }
                break;
            }
            }

            methodCallNode.RemoveFromGraph();
        }
 protected override void VisitBorderNode(NationalInstruments.Dfir.BorderNode borderNode)
 {
     _nodeFacade = AutoBorrowNodeFacade.GetNodeFacade(borderNode);
     this.VisitRebarNode(borderNode);
     _nodeFacade = null;
 }
 protected override void VisitNode(Node node)
 {
     _nodeFacade = AutoBorrowNodeFacade.GetNodeFacade(node);
     this.VisitRebarNode(node);
     _nodeFacade = null;
 }
Example #28
0
        public static void CreateFacadesForFunctionSignatureNode(this Node node, NIType nodeFunctionSignature)
        {
            int inputIndex = 0, outputIndex = 0;
            var genericTypeParameters  = new Dictionary <NIType, TypeVariableReference>();
            var lifetimeFacadeGroups   = new Dictionary <NIType, ReferenceInputTerminalLifetimeGroup>();
            var lifetimeVariableGroups = new Dictionary <NIType, LifetimeTypeVariableGroup>();

            TypeVariableSet      typeVariableSet = node.GetTypeVariableSet();
            AutoBorrowNodeFacade nodeFacade      = AutoBorrowNodeFacade.GetNodeFacade(node);

            TypeVariableReference[] signatureTypeParameters;
            if (nodeFunctionSignature.IsOpenGeneric())
            {
                Func <NIType, TypeVariableReference> createLifetimeTypeReference = type =>
                {
                    var group = LifetimeTypeVariableGroup.CreateFromNode(node);
                    lifetimeVariableGroups[type] = group;
                    return(group.LifetimeType);
                };
                genericTypeParameters = typeVariableSet.CreateTypeVariablesForGenericParameters(nodeFunctionSignature, createLifetimeTypeReference);

                signatureTypeParameters = nodeFunctionSignature.GetGenericParameters().Select(p => genericTypeParameters[p]).ToArray();
            }
            else
            {
                signatureTypeParameters = new TypeVariableReference[0];
            }
            var functionalNode = node as FunctionalNode;

            if (functionalNode != null)
            {
                functionalNode.FunctionType = new FunctionType(nodeFunctionSignature, signatureTypeParameters);
            }

            foreach (NIType parameter in nodeFunctionSignature.GetParameters())
            {
                NIType parameterDataType = parameter.GetDataType();
                bool   isInput = parameter.GetInputParameterPassingRule() != NIParameterPassingRule.NotAllowed,
                       isOutput = parameter.GetOutputParameterPassingRule() != NIParameterPassingRule.NotAllowed;
                Terminal inputTerminal = null, outputTerminal = null;
                if (isInput)
                {
                    inputTerminal = node.InputTerminals[inputIndex];
                    ++inputIndex;
                }
                if (isOutput)
                {
                    outputTerminal = node.OutputTerminals[outputIndex];
                    ++outputIndex;
                }
                if (isInput && isOutput)
                {
                    if (parameterDataType.IsRebarReferenceType())
                    {
                        CreateFacadesForInoutReferenceParameter(
                            typeVariableSet,
                            nodeFacade,
                            parameterDataType,
                            inputTerminal,
                            outputTerminal,
                            genericTypeParameters,
                            lifetimeFacadeGroups,
                            lifetimeVariableGroups);
                    }
                    else
                    {
                        throw new NotSupportedException("Inout parameters must be reference types.");
                    }
                }
                else if (isOutput)
                {
                    TypeVariableReference typeVariableReference = typeVariableSet.CreateTypeVariableReferenceFromNIType(parameterDataType, genericTypeParameters);
                    nodeFacade[outputTerminal] = new SimpleTerminalFacade(outputTerminal, typeVariableReference);
                }
                else if (isInput)
                {
                    if (parameterDataType.IsRebarReferenceType())
                    {
                        CreateFacadesForInoutReferenceParameter(
                            typeVariableSet,
                            nodeFacade,
                            parameterDataType,
                            inputTerminal,
                            null,
                            genericTypeParameters,
                            lifetimeFacadeGroups,
                            lifetimeVariableGroups);
                    }
                    else
                    {
                        TypeVariableReference typeVariableReference = typeVariableSet.CreateTypeVariableReferenceFromNIType(parameterDataType, genericTypeParameters);
                        nodeFacade[inputTerminal] = new SimpleTerminalFacade(inputTerminal, typeVariableReference);
                    }
                }
                else
                {
                    throw new NotSupportedException("Parameter is neither input nor output");
                }
            }
        }