bool IDfirNodeVisitor <bool> .VisitExplicitBorrowNode(ExplicitBorrowNode explicitBorrowNode) { if (explicitBorrowNode.AlwaysCreateReference && explicitBorrowNode.AlwaysBeginLifetime) { bool mutable = explicitBorrowNode.BorrowMode == BorrowMode.Mutable; Lifetime borrowLifetime = explicitBorrowNode.OutputTerminals.First().DefineLifetimeThatIsBoundedByDiagram(); TypeVariableReference borrowLifetimeType = _typeVariableSet.CreateReferenceToLifetimeType(borrowLifetime); foreach (var terminalPair in explicitBorrowNode.InputTerminals.Zip(explicitBorrowNode.OutputTerminals)) { Terminal inputTerminal = terminalPair.Key, outputTerminal = terminalPair.Value; TypeVariableReference inputTypeVariable = _typeVariableSet.CreateReferenceToNewTypeVariable(); _nodeFacade[inputTerminal] = new SimpleTerminalFacade(inputTerminal, inputTypeVariable); TypeVariableReference outputReferenceType = _typeVariableSet.CreateReferenceToReferenceType(mutable, inputTypeVariable, borrowLifetimeType); _nodeFacade[outputTerminal] = new SimpleTerminalFacade(outputTerminal, outputReferenceType); } } else { // TODO throw new NotImplementedException(); } return(true); }
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; }
bool IDfirNodeVisitor <bool> .VisitIterateTunnel(IterateTunnel iterateTunnel) { Terminal iteratorInput = iterateTunnel.InputTerminals.ElementAt(0), itemOutput = iterateTunnel.OutputTerminals.ElementAt(0); LifetimeTypeVariableGroup lifetimeTypeVariableGroup = LifetimeTypeVariableGroup.CreateFromTerminal(iteratorInput); TypeVariableReference loopLifetimeReference = _typeVariableSet.CreateReferenceToLifetimeType(itemOutput.GetDiagramLifetime()); TypeVariableReference itemTypeVariable = _typeVariableSet.CreateReferenceToNewTypeVariable(); TypeVariableReference implementsIteratorTypeVariable = _typeVariableSet.CreateReferenceToNewTypeVariable( new Constraint[] { new IteratorTraitConstraint(itemTypeVariable) }); ReferenceInputTerminalLifetimeGroup group = CreateTerminalLifetimeGroup(InputReferenceMutability.RequireMutable, lifetimeTypeVariableGroup); group.AddTerminalFacade(iteratorInput, implementsIteratorTypeVariable, default(TypeVariableReference)); _nodeFacade[itemOutput] = new SimpleTerminalFacade(itemOutput, itemTypeVariable); TypeVariableReference intermediateTypeVariable = _typeVariableSet.CreateReferenceToOptionType(itemTypeVariable); VariableReference intermediateVariable = iterateTunnel.GetVariableSet().CreateNewVariable( iterateTunnel.ParentStructure.ParentDiagram.GetLifetimeGraphIdentifier().Id, intermediateTypeVariable, false); intermediateVariable.Name = iterateTunnel.IntermediateValueName; iterateTunnel.IntermediateValueVariable = intermediateVariable; iterateTunnel.IteratorNextFunctionType = new FunctionType( Signatures.IteratorNextType, new TypeVariableReference[] { implementsIteratorTypeVariable, itemTypeVariable, group.LifetimeType }); return(true); }
bool IDfirNodeVisitor <bool> .VisitDropNode(DropNode dropNode) { Terminal valueInput = dropNode.InputTerminals.ElementAt(0); TypeVariableReference dataTypeVariable = _typeVariableSet.CreateReferenceToNewTypeVariable(); _nodeFacade[valueInput] = new SimpleTerminalFacade(valueInput, dataTypeVariable); return(true); }
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); }
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); }
bool IDfirNodeVisitor <bool> .VisitUnwrapOptionTunnel(UnwrapOptionTunnel unwrapOptionTunnel) { Terminal optionInput = unwrapOptionTunnel.InputTerminals[0], unwrappedOutput = unwrapOptionTunnel.OutputTerminals[0]; TypeVariableReference innerTypeVariable = _typeVariableSet.CreateReferenceToNewTypeVariable(); _nodeFacade[optionInput] = new SimpleTerminalFacade( optionInput, _typeVariableSet.CreateReferenceToOptionType(innerTypeVariable)); _nodeFacade[unwrappedOutput] = new SimpleTerminalFacade(unwrappedOutput, innerTypeVariable); return(true); }
bool IDfirNodeVisitor <bool> .VisitOptionPatternStructureSelector(OptionPatternStructureSelector optionPatternStructureSelector) { Terminal selectorInput = optionPatternStructureSelector.InputTerminals[0], selectorSomeOutput = optionPatternStructureSelector.OutputTerminals[0]; TypeVariableReference innerTypeVariable = _typeVariableSet.CreateReferenceToNewTypeVariable(), outerTypeReference = _typeVariableSet.CreateReferenceToOptionType(innerTypeVariable); _nodeFacade[selectorInput] = new SimpleTerminalFacade(selectorInput, outerTypeReference); _nodeFacade[selectorSomeOutput] = new SimpleTerminalFacade(selectorSomeOutput, innerTypeVariable); return(true); }
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> .VisitTerminateLifetimeTunnel(TerminateLifetimeTunnel terminateLifetimeTunnel) { Terminal valueOutput = terminateLifetimeTunnel.OutputTerminals.ElementAt(0); var valueFacade = new SimpleTerminalFacade(valueOutput, default(TypeVariableReference)); _nodeFacade[valueOutput] = valueFacade; NationalInstruments.Dfir.BorderNode beginLifetimeBorderNode = (NationalInstruments.Dfir.BorderNode)terminateLifetimeTunnel.BeginLifetimeTunnel; Terminal beginLifetimeTerminal = beginLifetimeBorderNode.GetOuterTerminal(0); valueFacade.FacadeVariable.MergeInto(beginLifetimeTerminal.GetFacadeVariable()); return(true); }
bool IDfirNodeVisitor <bool> .VisitVariantConstructorNode(VariantConstructorNode variantConstructorNode) { Terminal inputTerminal = variantConstructorNode.InputTerminals[0], outputTerminal = variantConstructorNode.OutputTerminals[0]; NIType elementType = variantConstructorNode.VariantType.GetFields().ElementAt(variantConstructorNode.SelectedFieldIndex).GetDataType(); _nodeFacade[inputTerminal] = new SimpleTerminalFacade( inputTerminal, _typeVariableSet.CreateTypeVariableReferenceFromNIType(elementType)); _nodeFacade[outputTerminal] = new SimpleTerminalFacade( outputTerminal, _typeVariableSet.CreateTypeVariableReferenceFromNIType(variantConstructorNode.VariantType)); 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); }
bool IDfirNodeVisitor <bool> .VisitStructConstructorNode(StructConstructorNode structConstructorNode) { NIType structType = structConstructorNode.Type; foreach (var pair in structConstructorNode.InputTerminals.Zip(structType.GetFields())) { Terminal inputTerminal = pair.Key; _nodeFacade[inputTerminal] = new SimpleTerminalFacade( inputTerminal, _typeVariableSet.CreateTypeVariableReferenceFromNIType(pair.Value.GetDataType())); } _nodeFacade[structConstructorNode.OutputTerminals[0]] = new SimpleTerminalFacade( structConstructorNode.OutputTerminals[0], _typeVariableSet.CreateTypeVariableReferenceFromNIType(structType)); return(true); }
bool IDfirNodeVisitor <bool> .VisitBorrowTunnel(BorrowTunnel borrowTunnel) { // T -> &'a (mode) T Terminal valueInput = borrowTunnel.InputTerminals.ElementAt(0), borrowOutput = borrowTunnel.OutputTerminals.ElementAt(0); TypeVariableReference dataTypeVariable = _typeVariableSet.CreateReferenceToNewTypeVariable(); Lifetime innerLifetime = borrowOutput.GetDiagramLifetime(); TypeVariableReference referenceType = _typeVariableSet.CreateReferenceToReferenceType( borrowTunnel.BorrowMode == BorrowMode.Mutable, dataTypeVariable, _typeVariableSet.CreateReferenceToLifetimeType(innerLifetime)); _nodeFacade[valueInput] = new SimpleTerminalFacade(valueInput, dataTypeVariable); _nodeFacade[borrowOutput] = new SimpleTerminalFacade(borrowOutput, referenceType); return(true); }
bool IDfirNodeVisitor <bool> .VisitDecomposeTupleNode(DecomposeTupleNode decomposeTupleNode) { TypeVariableReference[] elementTypes = new TypeVariableReference[decomposeTupleNode.OutputTerminals.Count]; TypeVariableReference mutabilityType = default(TypeVariableReference); ReferenceInputTerminalLifetimeGroup inputTerminalGroup = null; if (decomposeTupleNode.DecomposeMode == DecomposeMode.Borrow) { mutabilityType = _typeVariableSet.CreateReferenceToMutabilityType(); var lifetimeVariableGroup = LifetimeTypeVariableGroup.CreateFromNode(decomposeTupleNode); inputTerminalGroup = _nodeFacade.CreateInputLifetimeGroup( InputReferenceMutability.Polymorphic, lifetimeVariableGroup.LazyNewLifetime, lifetimeVariableGroup.LifetimeType); } for (int i = 0; i < decomposeTupleNode.OutputTerminals.Count; ++i) { Terminal outputTerminal = decomposeTupleNode.OutputTerminals[i]; TypeVariableReference elementType = _typeVariableSet.CreateReferenceToNewTypeVariable(); TypeVariableReference outputTerminalType = decomposeTupleNode.DecomposeMode == DecomposeMode.Borrow ? _typeVariableSet.CreateReferenceToPolymorphicReferenceType( mutabilityType, elementType, inputTerminalGroup.LifetimeType) : elementType; _nodeFacade[outputTerminal] = new SimpleTerminalFacade(outputTerminal, outputTerminalType); elementTypes[i] = elementType; } TypeVariableReference tupleType = _typeVariableSet.CreateReferenceToTupleType(elementTypes); Terminal inputTerminal = decomposeTupleNode.InputTerminals[0]; if (decomposeTupleNode.DecomposeMode == DecomposeMode.Borrow) { inputTerminalGroup.AddTerminalFacade( inputTerminal, tupleType, mutabilityType); } else { _nodeFacade[inputTerminal] = new SimpleTerminalFacade(inputTerminal, tupleType); } return(true); }
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); } }
bool IDfirNodeVisitor <bool> .VisitBuildTupleNode(BuildTupleNode buildTupleNode) { TypeVariableReference[] elementTypes = new TypeVariableReference[buildTupleNode.InputTerminals.Count]; for (int i = 0; i < buildTupleNode.InputTerminals.Count; ++i) { Terminal inputTerminal = buildTupleNode.InputTerminals[i]; // TODO: constrain these to be unbounded lifetime TypeVariableReference elementType = _typeVariableSet.CreateReferenceToNewTypeVariable(); _nodeFacade[inputTerminal] = new SimpleTerminalFacade(inputTerminal, elementType); elementTypes[i] = elementType; } TypeVariableReference tupleType = _typeVariableSet.CreateReferenceToTupleType(elementTypes); Terminal outputTerminal = buildTupleNode.OutputTerminals[0]; _nodeFacade[outputTerminal] = new SimpleTerminalFacade(outputTerminal, tupleType); return(true); }
bool IDfirNodeVisitor <bool> .VisitLoopConditionTunnel(LoopConditionTunnel loopConditionTunnel) { // TODO: how to determine the mutability of the outer loop condition variable? Terminal loopConditionInput = loopConditionTunnel.InputTerminals.ElementAt(0), loopConditionOutput = loopConditionTunnel.OutputTerminals.ElementAt(0); TypeVariableReference boolType = _typeVariableSet.CreateTypeVariableReferenceFromNIType(NITypes.Boolean); _nodeFacade[loopConditionInput] = new SimpleTerminalFacade(loopConditionInput, boolType); Lifetime innerLifetime = loopConditionOutput.GetDiagramLifetime(); TypeVariableReference boolReferenceType = _typeVariableSet.CreateReferenceToReferenceType( true, boolType, _typeVariableSet.CreateReferenceToLifetimeType(innerLifetime)); _nodeFacade[loopConditionOutput] = new SimpleTerminalFacade(loopConditionOutput, boolReferenceType); return(true); }
bool IDfirNodeVisitor <bool> .VisitIterateTunnel(IterateTunnel iterateTunnel) { Terminal iteratorInput = iterateTunnel.InputTerminals.ElementAt(0), itemOutput = iterateTunnel.OutputTerminals.ElementAt(0); LifetimeTypeVariableGroup lifetimeTypeVariableGroup = LifetimeTypeVariableGroup.CreateFromTerminal(iteratorInput); TypeVariableReference loopLifetimeReference = _typeVariableSet.CreateReferenceToLifetimeType(itemOutput.GetDiagramLifetime()); TypeVariableReference itemTypeVariable = _typeVariableSet.CreateReferenceToNewTypeVariable(); TypeVariableReference implementsIteratorTypeVariable = _typeVariableSet.CreateReferenceToNewTypeVariable( new Constraint[] { new IteratorTraitConstraint(itemTypeVariable) }); _nodeFacade .CreateInputLifetimeGroup(InputReferenceMutability.RequireMutable, lifetimeTypeVariableGroup.LazyNewLifetime, lifetimeTypeVariableGroup.LifetimeType) .AddTerminalFacade(iteratorInput, implementsIteratorTypeVariable, default(TypeVariableReference)); _nodeFacade[itemOutput] = new SimpleTerminalFacade(itemOutput, itemTypeVariable); return(true); }
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); }
bool IDfirNodeVisitor <bool> .VisitLockTunnel(LockTunnel lockTunnel) { Terminal lockInput = lockTunnel.InputTerminals.ElementAt(0), referenceOutput = lockTunnel.OutputTerminals.ElementAt(0); LifetimeTypeVariableGroup lifetimeTypeVariableGroup = LifetimeTypeVariableGroup.CreateFromTerminal(lockInput); TypeVariableReference dataVariableType = _typeVariableSet.CreateReferenceToNewTypeVariable(); TypeVariableReference lockType = _typeVariableSet.CreateReferenceToLockingCellType(dataVariableType); CreateTerminalLifetimeGroup(InputReferenceMutability.AllowImmutable, lifetimeTypeVariableGroup) .AddTerminalFacade(lockInput, lockType, default(TypeVariableReference)); Lifetime innerLifetime = referenceOutput.GetDiagramLifetime(); TypeVariableReference referenceType = _typeVariableSet.CreateReferenceToReferenceType( true, lockType, _typeVariableSet.CreateReferenceToLifetimeType(innerLifetime)); _nodeFacade[referenceOutput] = new SimpleTerminalFacade(referenceOutput, referenceType); return(true); }
bool IDfirNodeVisitor <bool> .VisitVariantMatchStructureSelector(VariantMatchStructureSelector variantMatchStructureSelector) { var fieldTypes = new Dictionary <string, TypeVariableReference>(); int fieldIndex = 0; foreach (var outputTerminal in variantMatchStructureSelector.OutputTerminals) { string fieldName = $"_{fieldIndex}"; TypeVariableReference fieldType = _typeVariableSet.CreateReferenceToNewTypeVariable(); fieldTypes[fieldName] = fieldType; _nodeFacade[outputTerminal] = new SimpleTerminalFacade(outputTerminal, fieldType); ++fieldIndex; } TypeVariableReference fieldedType = _typeVariableSet.CreateReferenceToIndefiniteFieldedType(fieldTypes); Terminal inputTerminal = variantMatchStructureSelector.InputTerminals[0]; _nodeFacade[inputTerminal] = new SimpleTerminalFacade(inputTerminal, fieldedType); return(true); }
bool IDfirNodeVisitor <bool> .VisitConstant(Constant constant) { Terminal valueOutput = constant.OutputTerminals.ElementAt(0); TypeVariableReference constantTypeReference; if (constant.DataType.IsRebarReferenceType()) { constantTypeReference = _typeVariableSet.CreateReferenceToReferenceType( false, // TODO: this is not always correct; need a more general way of turning NITypes into TypeVariableReferences _typeVariableSet.CreateTypeVariableReferenceFromNIType(constant.DataType.GetReferentType()), // Assume for now that the reference will be in Lifetime.Static _typeVariableSet.CreateReferenceToLifetimeType(Lifetime.Static)); } else { constantTypeReference = _typeVariableSet.CreateTypeVariableReferenceFromNIType(constant.DataType); } _nodeFacade[valueOutput] = new SimpleTerminalFacade(valueOutput, constantTypeReference); return(true); }
bool IDfirNodeVisitor <bool> .VisitStructFieldAccessorNode(StructFieldAccessorNode structFieldAccessorNode) { TypeVariableReference mutabilityType = _typeVariableSet.CreateReferenceToMutabilityType(); var lifetimeVariableGroup = LifetimeTypeVariableGroup.CreateFromNode(structFieldAccessorNode); ReferenceInputTerminalLifetimeGroup inputTerminalGroup = CreateTerminalLifetimeGroup( InputReferenceMutability.Polymorphic, lifetimeVariableGroup); var fieldTypes = new Dictionary <string, TypeVariableReference>(); foreach (var terminalPair in structFieldAccessorNode.OutputTerminals.Zip(structFieldAccessorNode.FieldNames)) { string fieldName = terminalPair.Value; TypeVariableReference fieldType; if (string.IsNullOrEmpty(fieldName)) { fieldType = _typeVariableSet.CreateReferenceToNewTypeVariable(); } else if (!fieldTypes.TryGetValue(fieldName, out fieldType)) { fieldType = _typeVariableSet.CreateReferenceToNewTypeVariable(); fieldTypes[fieldName] = fieldType; } TypeVariableReference terminalTypeVariable = _typeVariableSet.CreateReferenceToPolymorphicReferenceType( mutabilityType, fieldType, inputTerminalGroup.LifetimeType); Terminal outputTerminal = terminalPair.Key; _nodeFacade[outputTerminal] = new SimpleTerminalFacade(outputTerminal, terminalTypeVariable); } TypeVariableReference fieldedType = _typeVariableSet.CreateReferenceToIndefiniteFieldedType(fieldTypes); inputTerminalGroup.AddTerminalFacade( structFieldAccessorNode.StructInputTerminal, fieldedType, mutabilityType); return(true); }
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); } }
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(); }
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"); } } }