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)); } }
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(); }
public static VariableReference CreateNewVariableForUnwiredTerminal(this Terminal terminal) { VariableSet variableSet = terminal.GetVariableSet(); return(variableSet.CreateNewVariable(terminal.ParentDiagram.UniqueId, variableSet.TypeVariableSet.CreateReferenceToNewTypeVariable())); }
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(); }