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; string typeName = TypeVariableSet.GetTypeName(underlyingType); bool underlyingTypeIsStringSlice = typeName == DataTypes.StringSliceType.GetName(), underlyingTypeIsString = typeName == NITypes.String.GetName(); bool inputCoercesToStringSlice = underlyingTypeIsString || underlyingTypeIsStringSlice; bool needsBorrow = !otherIsReference || !underlyingTypeIsStringSlice; 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.CreateTypeVariableReferenceFromNIType(DataTypes.StringSliceType) : underlyingType; return(TypeVariableSet.CreateReferenceToReferenceType( false, toUnifyUnderlyingType, lifetimeType)); }
public void AddTerminalFacade(Terminal inputTerminal, TypeVariableReference referentTypeReference, TypeVariableReference mutabilityTypeReference, Terminal terminateLifetimeOutputTerminal = null) { TypeVariableReference referenceType; TypeVariableSet typeVariableSet = inputTerminal.GetTypeVariableSet(); if (_mutability == InputReferenceMutability.Polymorphic) { referenceType = typeVariableSet.CreateReferenceToPolymorphicReferenceType( mutabilityTypeReference, referentTypeReference, LifetimeType); } else { referenceType = typeVariableSet.CreateReferenceToReferenceType( (_mutability != InputReferenceMutability.AllowImmutable), referentTypeReference, LifetimeType); } if (_lazyBorrowLifetime.IsValueCreated) { throw new InvalidOperationException("Cannot add borrowed variables after creating new lifetime."); } bool isStringSliceReference = typeVariableSet.GetTypeName(referentTypeReference) == DataTypes.StringSliceType.GetName(); TerminalFacade terminalFacade; if (isStringSliceReference) { terminalFacade = new StringSliceReferenceInputTerminalFacade(inputTerminal, this, referenceType); } else { terminalFacade = new ReferenceInputTerminalFacade(inputTerminal, _mutability, this, referenceType); } _nodeFacade[inputTerminal] = terminalFacade; _facades.Add(terminalFacade); if (terminateLifetimeOutputTerminal != null) { var outputFacade = new TerminateLifetimeOutputTerminalFacade(terminateLifetimeOutputTerminal, terminalFacade); _nodeFacade[terminateLifetimeOutputTerminal] = outputFacade; } }
public override void UnifyWithConnectedWireTypeAsNodeInput(VariableReference wireFacadeVariable, ITypeUnificationResultFactory unificationResultFactory) { TypeVariableSet typeVariableSet = Terminal.GetTypeVariableSet(); Terminal.UnifyTerminalTypeWith(TrueVariable.TypeVariableReference, wireFacadeVariable.TypeVariableReference, unificationResultFactory); TrueVariable.MergeInto(wireFacadeVariable); TypeVariableReference optionType; if (typeVariableSet.GetTypeName(TrueVariable.TypeVariableReference) == "Option") { optionType = TrueVariable.TypeVariableReference; } else { optionType = typeVariableSet.CreateReferenceToOptionType(TrueVariable.TypeVariableReference); } TypeVariableReference outputTypeReference = _outputTerminalFacade.TrueVariable.TypeVariableReference; _outputTerminalFacade.Terminal.UnifyTerminalTypeWith(outputTypeReference, optionType, unificationResultFactory); }