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); }
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); }
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); }
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)); }
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); } }
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); }
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); }
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); } }
bool IDfirNodeVisitor <bool> .VisitFunctionalNode(FunctionalNode functionalNode) { AutoBorrowNodeFacade.GetNodeFacade(functionalNode).SetLifetimeInterruptedVariables(_lifetimeVariableAssociation); return(true); }
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); }
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; }
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"); } } }
protected override void VisitNode(Node node) { AutoBorrowNodeFacade.GetNodeFacade(node).FinalizeAutoBorrows(); }
/// <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()); }
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(BorderNode borderNode) { AutoBorrowNodeFacade.GetNodeFacade(borderNode).FinalizeAutoBorrows(); }