Exemplo n.º 1
0
        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 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.");
            }

            NIType literalReferentType;
            bool   isStringSliceReference = typeVariableSet.TryGetLiteralType(referentTypeReference, out literalReferentType) &&
                                            literalReferentType == DataTypes.StringSliceType;
            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;
            }
        }