public BuildResult(NodePlugin plugin, CilCompilation compilation, IOperationDefinitionSymbol operation, IMethodDefinition methodToCall, MethodInfo clrMethodToCall, EvalAction evaluateAction, string error) { Plugin = plugin; Compilation = compilation; Operation = operation; MethodToCall = methodToCall; ClrMethodToCall = clrMethodToCall; EvaluateAction = evaluateAction; Error = error; }
// Called on main thread public void Initialize(Host vlHost, IHDEHost hdeHost, ILogger logger) { FVlHost = vlHost; FPlatform = (Platform)FVlHost.Session.TargetPlatform; FHDEHost = hdeHost; FLogger = logger; FHDEHost.MainLoop.OnResetCache += HandleMainLoopOnResetCache; FCompilation = FPlatform.LatestCompilation; Clocks.FRealTimeClock = new HDERealTimeClock(FHDEHost); FHDEHost.MainLoop.OnInitFrame += MainLoop_OnInitFrame; }
public async Task UpdateAsync(CilCompilation compilation, CancellationToken token) { try { var results = new List <NodePlugin.BuildResult>(FInstances.Length); foreach (var instance in FInstances) { var buildResult = await Task.Run(() => instance.Update(compilation), token); results.Add(buildResult); } token.ThrowIfCancellationRequested(); using (var swapper = new HotSwapper(Compilation, compilation, token)) { foreach (var result in results) { var instance = result.Plugin; if (!instance.IsDisposed) // It could be that the node has already been deleted { instance.SyncPinsAndRestoreState(result, swapper); } } ImplicitEntryPointInstanceManager.Update(swapper); Compilation = compilation; } } catch (OperationCanceledException) { // Fine } catch (Exception e) { LogAndStop(e); } }
public BuildResult WithCompilation(CilCompilation compilation) => compilation != Compilation ? new BuildResult(Plugin, compilation, Operation, MethodToCall, ClrMethodToCall, EvaluateAction, Error) : this;
// Gets called on background thread. Does not write to any fields. All results get returned on stack. public BuildResult Update(CilCompilation compilation) { if (compilation == FBuildResult.Compilation) { return(FBuildResult); // Same compilation, nothing to do } if (compilation.Age < FBuildResult.Compilation?.Age) { return(FBuildResult); // Dismiss outdated compilations } var definitionSymbol = compilation.EntryPoints.FirstOrDefault(e => e.Node.Identity == NodeId) as INodeDefinitionSymbol; if (definitionSymbol == null) { return(FBuildResult.WithError($"Couldn't find entry point with id {NodeId} in compilation.")); } var closedDefinitionSymbol = definitionSymbol.GetClosedOrDefault(definitionSymbol.DocSymbols); if (closedDefinitionSymbol == null) { return(FBuildResult.WithError($"Couldn't close the generic node {definitionSymbol}.")); } // Look for the desired operation and build our evaluate method around it IMethodDefinition methodToCall; var processDefinitionSymbol = closedDefinitionSymbol as IProcessDefinitionSymbol; if (processDefinitionSymbol != null) { // TODO: Rewrite me to support process nodes fully (calling all its operations!) var updateOperation = processDefinitionSymbol.Operations.FirstOrDefault(p => p.Name == NameAndVersion.Update); if (updateOperation == null) { return(FBuildResult.WithError($"Couldn't find 'Update' operation in {processDefinitionSymbol}.")); } methodToCall = compilation.GetCciMethod(updateOperation); } else { methodToCall = compilation.GetCciMethod((IOperationDefinitionSymbol)closedDefinitionSymbol); } if (methodToCall == null) { return(FBuildResult.WithError($"Couldn't find suitable method to call in evaluate for node {closedDefinitionSymbol}.")); } if (methodToCall.IsGeneric) { return(FBuildResult.WithError($"The method {methodToCall} must not be generic. Use the closed flag or annotate in- and output pins to avoid generic nodes.")); } var containingType = methodToCall.ContainingTypeDefinition; if (containingType.IsGeneric) { return(FBuildResult.WithError($"The containing type {containingType} must not be generic. Use the closed flag or annotate in- and output pins to avoid generic nodes.")); } // Only if the method changed our pins need to be synced and our state restored if (methodToCall != FBuildResult.MethodToCall) { var scope = closedDefinitionSymbol.DocSymbols; var operation = compilation.GetVlOperation(methodToCall, scope); var stateOutput = operation.GetStateOutput(); var returnValueIsState = !methodToCall.IsStatic; var builder = new EvaluateMethodBuilder(FVlHost, compilation, scope, returnValueIsState); var evaluateAction = builder.Build(methodToCall); return(new BuildResult( plugin: this, compilation: compilation, operation: operation, methodToCall: methodToCall, clrMethodToCall: (MethodInfo)compilation.GetClrMethod(methodToCall), evaluateAction: evaluateAction, error: null)); } // Remember the new compilation so we can exit early in subsequent calls return(FBuildResult.WithCompilation(compilation)); }