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; }
protected override TypeVariableReference ComputeTypeToUnifyWith(VariableReference inputFacadeVariable, out bool setExpectedMutable) { setExpectedMutable = false; TypeVariableReference other = inputFacadeVariable.TypeVariableReference; TypeVariableReference u, l; bool otherIsMutableReference; bool otherIsReference = TypeVariableSet.TryDecomposeReferenceType(other, out u, out l, out otherIsMutableReference); TypeVariableReference underlyingType = otherIsReference ? u : other; NIType literalType; bool underlyingTypeIsLiteral = TypeVariableSet.TryGetLiteralType(underlyingType, out literalType); bool inputCoercesToStringSlice = underlyingTypeIsLiteral && (literalType == PFTypes.String || literalType == DataTypes.StringSliceType); bool needsBorrow = !otherIsReference || !underlyingTypeIsLiteral || literalType != DataTypes.StringSliceType; TypeVariableReference lifetimeType = otherIsReference ? l : TypeVariableSet.CreateReferenceToLifetimeType(_group.BorrowLifetime); if (needsBorrow) { _stringToSliceNeeded = true; _group.SetBorrowRequired(false); } // If the input is allowed to coerce to a str, we can unify with str; // otherwise, unify with the underlying type to get a type mismatch. TypeVariableReference toUnifyUnderlyingType = inputCoercesToStringSlice ? TypeVariableSet.CreateReferenceToLiteralType(DataTypes.StringSliceType) : underlyingType; return(TypeVariableSet.CreateReferenceToReferenceType( false, toUnifyUnderlyingType, lifetimeType)); }
protected override TypeVariableReference ComputeTypeToUnifyWith(VariableReference inputFacadeVariable, out bool setExpectedMutable) { TypeVariableReference other = inputFacadeVariable.TypeVariableReference; TypeVariableReference u, otherReferenceLifetime; bool otherIsMutableReference; bool otherIsReference = TypeVariableSet.TryDecomposeReferenceType(other, out u, out otherReferenceLifetime, out otherIsMutableReference); TypeVariableReference underlyingType = otherIsReference ? u : other; bool mutable = otherIsReference ? otherIsMutableReference : inputFacadeVariable.Mutable; TypeVariableReference typeToUnifyWith = default(TypeVariableReference); setExpectedMutable = false; switch (_mutability) { case InputReferenceMutability.RequireMutable: { TypeVariableReference lifetimeType; if (!otherIsReference) { _group.SetBorrowRequired(true); lifetimeType = TypeVariableSet.CreateReferenceToLifetimeType(_group.BorrowLifetime); } else { lifetimeType = otherReferenceLifetime; } typeToUnifyWith = TypeVariableSet.CreateReferenceToReferenceType(true, underlyingType, lifetimeType); setExpectedMutable = !mutable; break; } case InputReferenceMutability.AllowImmutable: { bool needsBorrow = !(otherIsReference && !otherIsMutableReference); TypeVariableReference lifetimeType; if (needsBorrow) { lifetimeType = TypeVariableSet.CreateReferenceToLifetimeType(_group.BorrowLifetime); _group.SetBorrowRequired(false); } else { lifetimeType = otherReferenceLifetime; } typeToUnifyWith = TypeVariableSet.CreateReferenceToReferenceType(false, underlyingType, lifetimeType); break; } case InputReferenceMutability.Polymorphic: { TypeVariableReference lifetimeType; if (!otherIsReference) { _group.SetBorrowRequired(false /* TODO depends on current state and input mutability */); lifetimeType = TypeVariableSet.CreateReferenceToLifetimeType(_group.BorrowLifetime); } else { // TODO: if TrueVariable.TypeVariableReference is already known to be immutable and // wire reference is mutable, then we need a borrow lifetimeType = otherReferenceLifetime; } typeToUnifyWith = TypeVariableSet.CreateReferenceToReferenceType(mutable, underlyingType, lifetimeType); break; } } return(typeToUnifyWith); }