예제 #1
0
        public static TerminateLifetimeNode CreateTerminateLifetimeWithFacades(Diagram parentDiagram, int inputs, int outputs)
        {
            var terminateLifetime = new TerminateLifetimeNode(parentDiagram, inputs, outputs);
            AutoBorrowNodeFacade terminateLifetimeFacade = AutoBorrowNodeFacade.GetNodeFacade(terminateLifetime);
            TypeVariableSet      typeVariableSet         = parentDiagram.GetTypeVariableSet();

            foreach (var terminal in terminateLifetime.Terminals)
            {
                terminateLifetimeFacade[terminal] = new SimpleTerminalFacade(terminal, typeVariableSet.CreateReferenceToNewTypeVariable());
            }
            return(terminateLifetime);
        }
예제 #2
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);
        }
예제 #3
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);
        }
예제 #4
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);
            }
        }
        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));
        }
예제 #6
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);
            }
        }
        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);
            }
        }
예제 #8
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);
        }
예제 #9
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);
        }
예제 #10
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);
        }
예제 #11
0
        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);
            }
        }
예제 #12
0
 bool IDfirNodeVisitor <bool> .VisitFunctionalNode(FunctionalNode functionalNode)
 {
     AutoBorrowNodeFacade.GetNodeFacade(functionalNode).SetLifetimeInterruptedVariables(_lifetimeVariableAssociation);
     return(true);
 }
예제 #13
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);
 }
예제 #15
0
 protected override void VisitBorderNode(NationalInstruments.Dfir.BorderNode borderNode)
 {
     _nodeFacade = AutoBorrowNodeFacade.GetNodeFacade(borderNode);
     this.VisitRebarNode(borderNode);
     _nodeFacade = null;
 }
예제 #16
0
 protected override void VisitNode(Node node)
 {
     _nodeFacade = AutoBorrowNodeFacade.GetNodeFacade(node);
     this.VisitRebarNode(node);
     _nodeFacade = null;
 }
예제 #17
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");
                }
            }
        }
예제 #18
0
 protected override void VisitNode(Node node)
 {
     AutoBorrowNodeFacade.GetNodeFacade(node).FinalizeAutoBorrows();
 }
예제 #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());
        }
예제 #20
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();
        }
예제 #21
0
 protected override void VisitBorderNode(BorderNode borderNode)
 {
     AutoBorrowNodeFacade.GetNodeFacade(borderNode).FinalizeAutoBorrows();
 }