public static DecomposeTupleNode CreateDecomposeTupleNodeWithFacades(Diagram parentDiagram, int elementCount, DecomposeMode decomposeMode) { var decomposeTupleNode = new DecomposeTupleNode(parentDiagram, elementCount, decomposeMode); decomposeTupleNode.CreateFacadesForDecomposeTupleNode(parentDiagram.GetTypeVariableSet()); return(decomposeTupleNode); }
public void DecomposeTupleNodeWithUnwiredInput_ValidateVariableUsages_ErrorOnUnwiredInput() { DfirRoot function = DfirRoot.Create(); var decomposeTuple = new DecomposeTupleNode(function.BlockDiagram, 2, DecomposeMode.Borrow); RunSemanticAnalysisUpToValidation(function); AssertTerminalHasRequiredTerminalUnconnectedMessage(decomposeTuple.InputTerminals[0]); }
internal static DecomposeTupleNode InsertDecompositionForTupleVariable(Diagram parentDiagram, LiveVariable liveTupleVariable, ITypeUnificationResultFactory unificationResultFactory) { NIType variableType = liveTupleVariable.Variable.Type; DecomposeTupleNode decomposeTuple = TupleNodeHelpers.CreateDecomposeTupleNodeWithFacades( parentDiagram, variableType.GetFields().Count(), DecomposeMode.Move); Terminal tupleInputTerminal = decomposeTuple.InputTerminals[0]; liveTupleVariable.ConnectToTerminalAsInputAndUnifyVariables( tupleInputTerminal, unificationResultFactory); return(decomposeTuple); }
bool IDfirNodeVisitor <bool> .VisitDecomposeTupleNode(DecomposeTupleNode decomposeTupleNode) { Terminal inputTerminal = decomposeTupleNode.InputTerminals[0]; if (decomposeTupleNode.DecomposeMode == DecomposeMode.Borrow) { MarkFacadeVariableOfTerminalInterrupted(inputTerminal); } MarkTrueVariableOfTerminalConsumed(inputTerminal); foreach (Terminal outputTerminal in decomposeTupleNode.OutputTerminals) { MarkFacadeVariableOfTerminalLive(outputTerminal); } 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); }
public void DecomposeTupleElementRefsNode_SetVariableTypes_OutputsAreElementRefTypes() { DfirRoot function = DfirRoot.Create(); BuildTupleNode buildTuple = new BuildTupleNode(function.BlockDiagram, 2); ConnectConstantToInputTerminal(buildTuple.InputTerminals[0], NITypes.Int32, false); ConnectConstantToInputTerminal(buildTuple.InputTerminals[1], NITypes.Boolean, false); var decomposeTuple = new DecomposeTupleNode(function.BlockDiagram, 2, DecomposeMode.Borrow); Wire.Create(function.BlockDiagram, buildTuple.OutputTerminals[0], decomposeTuple.InputTerminals[0]); RunSemanticAnalysisUpToSetVariableTypes(function); VariableReference decomposeOutputVariable0 = decomposeTuple.OutputTerminals[0].GetTrueVariable(), decomposeOutputVariable1 = decomposeTuple.OutputTerminals[1].GetTrueVariable(); Assert.IsTrue(decomposeOutputVariable0.Type.GetReferentType().IsInt32()); Assert.IsTrue(decomposeOutputVariable1.Type.GetReferentType().IsBoolean()); }
public void BuildTupleAndDecomposeTupleAsMove_Execute_CorrectElementValues() { DfirRoot function = DfirRoot.Create(); BuildTupleNode buildTuple = new BuildTupleNode(function.BlockDiagram, 2); ConnectConstantToInputTerminal(buildTuple.InputTerminals[0], NITypes.Int32, 1, false); ConnectConstantToInputTerminal(buildTuple.InputTerminals[1], NITypes.Boolean, true, false); var decomposeTuple = new DecomposeTupleNode(function.BlockDiagram, 2, DecomposeMode.Move); Wire.Create(function.BlockDiagram, buildTuple.OutputTerminals[0], decomposeTuple.InputTerminals[0]); FunctionalNode inspect0 = ConnectInspectToOutputTerminal(decomposeTuple.OutputTerminals[0]), inspect1 = ConnectInspectToOutputTerminal(decomposeTuple.OutputTerminals[1]); TestExecutionInstance executionInstance = CompileAndExecuteFunction(function); byte[] inspectValue = executionInstance.GetLastValueFromInspectNode(inspect0); AssertByteArrayIsInt32(inspectValue, 1); inspectValue = executionInstance.GetLastValueFromInspectNode(inspect1); AssertByteArrayIsBoolean(inspectValue, true); }
public void UnconsumedTupleVariable_AutomaticNodeInsertion_TupleIsMoveDecomposedAndElementsAreDropped() { DfirRoot function = DfirRoot.Create(); BuildTupleNode buildTuple = new BuildTupleNode(function.BlockDiagram, 2); ConnectConstantToInputTerminal(buildTuple.InputTerminals[0], NITypes.Int32, false); ConnectConstantToInputTerminal(buildTuple.InputTerminals[1], NITypes.Boolean, false); RunCompilationUpToAutomaticNodeInsertion(function); DecomposeTupleNode decomposeTuple = AssertDiagramContainsNodeWithSources <DecomposeTupleNode>(function.BlockDiagram, buildTuple.OutputTerminals[0]); Assert.AreEqual(DecomposeMode.Move, decomposeTuple.DecomposeMode); AssertVariablesReferenceSame(buildTuple.OutputTerminals[0].GetTrueVariable(), decomposeTuple.InputTerminals[0].GetTrueVariable()); Assert.AreEqual(2, decomposeTuple.OutputTerminals.Count); DropNode drop0 = AssertDiagramContainsNodeWithSources <DropNode>(function.BlockDiagram, decomposeTuple.OutputTerminals[0]); AssertDropInputVariableHasType(drop0, NITypes.Int32); DropNode drop1 = AssertDiagramContainsNodeWithSources <DropNode>(function.BlockDiagram, decomposeTuple.OutputTerminals[1]); AssertDropInputVariableHasType(drop1, NITypes.Boolean); }
private static void CreateFacadesForDecomposeTupleNode(this DecomposeTupleNode decomposeTupleNode, TypeVariableSet typeVariableSet) { if (decomposeTupleNode.DecomposeMode == DecomposeMode.Borrow) { throw new NotSupportedException(); } TypeVariableReference[] elementTypes = new TypeVariableReference[decomposeTupleNode.OutputTerminals.Count]; AutoBorrowNodeFacade nodeFacade = AutoBorrowNodeFacade.GetNodeFacade(decomposeTupleNode); for (int i = 0; i < decomposeTupleNode.OutputTerminals.Count; ++i) { Terminal outputTerminal = decomposeTupleNode.OutputTerminals[i]; TypeVariableReference elementType = typeVariableSet.CreateReferenceToNewTypeVariable(); nodeFacade[outputTerminal] = new SimpleTerminalFacade(outputTerminal, elementType); elementTypes[i] = elementType; } TypeVariableReference tupleType = typeVariableSet.CreateReferenceToTupleType(elementTypes); Terminal inputTerminal = decomposeTupleNode.InputTerminals[0]; nodeFacade[inputTerminal] = new SimpleTerminalFacade(inputTerminal, tupleType); }
public void Execute(DfirRoot dfirRoot, CompileCancellationToken cancellationToken) { LiveVariable liveUnboundedLifetimeVariable; while (_lifetimeVariableAssociation.TryGetLiveVariableWithUnboundedLifetime(out liveUnboundedLifetimeVariable)) { Diagram parentDiagram = liveUnboundedLifetimeVariable.Terminal.ParentDiagram; NIType variableType = liveUnboundedLifetimeVariable.Variable.Type; if (variableType.IsCluster()) { DecomposeTupleNode decomposeTuple = InsertDecompositionForTupleVariable( parentDiagram, liveUnboundedLifetimeVariable, _unificationResultFactory); foreach (Terminal outputTerminal in decomposeTuple.OutputTerminals) { _lifetimeVariableAssociation.MarkVariableLive(outputTerminal.GetFacadeVariable(), outputTerminal); } _lifetimeVariableAssociation.MarkVariableConsumed(liveUnboundedLifetimeVariable.Variable); continue; } if (variableType.IsValueClass() && variableType.GetFields().Any()) { DecomposeStructNode decomposeStruct = InsertDecompositionForStructVariable( parentDiagram, liveUnboundedLifetimeVariable, _unificationResultFactory); foreach (Terminal outputTerminal in decomposeStruct.OutputTerminals) { _lifetimeVariableAssociation.MarkVariableLive(outputTerminal.GetFacadeVariable(), outputTerminal); } _lifetimeVariableAssociation.MarkVariableConsumed(liveUnboundedLifetimeVariable.Variable); continue; } InsertDropForVariable(parentDiagram, liveUnboundedLifetimeVariable, _unificationResultFactory); _lifetimeVariableAssociation.MarkVariableConsumed(liveUnboundedLifetimeVariable.Variable); } }
bool IDfirNodeVisitor <bool> .VisitDecomposeTupleNode(DecomposeTupleNode decomposeTupleNode) { ValidateRequiredInputTerminal(decomposeTupleNode.InputTerminals[0]); return(true); }
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(); }
bool IDfirNodeVisitor <bool> .VisitDecomposeTupleNode(DecomposeTupleNode decomposeTupleNode) { decomposeTupleNode.UnifyNodeInputTerminalTypes(_typeUnificationResults); return(true); }