Example #1
0
        public static VariableReference CreateNewVariableForUnwiredTerminal(this Terminal terminal)
        {
            VariableSet variableSet       = terminal.GetVariableSet();
            int         diagramLifetimeId = terminal.ParentDiagram.GetLifetimeGraphIdentifier().Id;

            return(variableSet.CreateNewVariable(diagramLifetimeId, variableSet.TypeVariableSet.CreateReferenceToNewTypeVariable()));
        }
 bool IDfirStructureVisitor <bool> .VisitFrame(Frame frame, StructureTraversalPoint traversalPoint)
 {
     if (traversalPoint == StructureTraversalPoint.BeforeLeftBorderNodes && frame.DoesStructureExecuteConditionally())
     {
         VariableSet       variableSet       = frame.GetVariableSet();
         VariableReference conditionVariable = variableSet.CreateNewVariable(
             frame.ParentDiagram.GetLifetimeGraphIdentifier().Id,
             variableSet.TypeVariableSet.CreateTypeVariableReferenceFromNIType(NITypes.Boolean),
             true);
         frame.SetConditionVariable(conditionVariable);
     }
     return(true);
 }
        protected override void VisitDfirRoot(DfirRoot dfirRoot)
        {
            base.VisitDfirRoot(dfirRoot);
            _typeVariableSet = dfirRoot.GetTypeVariableSet();
            var variableSet = new VariableSet(_typeVariableSet);

            dfirRoot.SetVariableSet(variableSet);

            int rootDiagramLifetimeId = 0;

            foreach (DataItem dataItem in dfirRoot.DataItems)
            {
                // TODO: eventually we want to reuse each DataItem's variable for its DataAccessors' terminals.
                TypeVariableReference dataTypeVariable = _typeVariableSet.CreateTypeVariableReferenceFromNIType(dataItem.DataType);
                dataItem.SetVariable(variableSet.CreateNewVariable(rootDiagramLifetimeId, dataTypeVariable, true));
            }
        }
Example #4
0
        private void DecomposeAsyncFunctionalNode(FunctionalNode functionalNode, NIType createPromiseSignature)
        {
            if (functionalNode.OutputTerminals.HasMoreThan(1))
            {
                throw new NotSupportedException("Decomposing FunctionalNodes with multiple output parameters not supported yet.");
            }

            FunctionalNode createPromiseNode = CreateInputReplacementNode(functionalNode, diagram => CreateFunctionalNodeWithFacade(diagram, createPromiseSignature));
            AwaitNode      awaitNode         = ConnectNewNodeToOutputTerminal(createPromiseNode, diagram => new AwaitNode(diagram));

            ConnectOutputTerminal(functionalNode.OutputTerminals[0], awaitNode.OutputTerminal);

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

            functionalNode.RemoveFromGraph();
        }
Example #5
0
        public static VariableReference CreateNewVariableForUnwiredTerminal(this Terminal terminal)
        {
            VariableSet variableSet = terminal.GetVariableSet();

            return(variableSet.CreateNewVariable(terminal.ParentDiagram.UniqueId, variableSet.TypeVariableSet.CreateReferenceToNewTypeVariable()));
        }
Example #6
0
        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();
        }