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