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> .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);
        }
        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);
        }