private static FScheme.Expression CompileFunction( FunctionDefinition definition ) { if (definition == null) return null; // Get the internal nodes for the function dynWorkspace functionWorkspace = definition.Workspace; #region Find outputs // Find output elements for the node IEnumerable<dynNode> outputs = functionWorkspace.Nodes.Where(x => x is dynOutput); var topMost = new List<Tuple<int, dynNode>>(); IEnumerable<string> outputNames; // if we found output nodes, add select their inputs // these will serve as the function output if (outputs.Any()) { topMost.AddRange( outputs.Where(x => x.HasInput(0)).Select(x => x.Inputs[0])); outputNames = outputs.Select(x => (x as dynOutput).Symbol); } else { // if there are no explicitly defined output nodes // get the top most nodes and set THEM as tht output IEnumerable<dynNode> topMostNodes = functionWorkspace.GetTopMostNodes(); var outNames = new List<string>(); foreach (dynNode topNode in topMostNodes) { foreach (int output in Enumerable.Range(0, topNode.OutPortData.Count)) { if (!topNode.HasOutput(output)) { topMost.Add(Tuple.Create(output, topNode)); outNames.Add(topNode.OutPortData[output].NickName); } } } outputNames = outNames; } #endregion // color the node to define its connectivity foreach (var ele in topMost) { ele.Item2.NodeUI.ValidateConnections(); } //Find function entry point, and then compile the function and add it to our environment IEnumerable<dynNode> variables = functionWorkspace.Nodes.Where(x => x is dynSymbol); IEnumerable<string> inputNames = variables.Select(x => (x as dynSymbol).Symbol); INode top; var buildDict = new Dictionary<dynNode, Dictionary<int, INode>>(); if (topMost.Count > 1) { InputNode node = new ExternalFunctionNode( FScheme.Value.NewList, Enumerable.Range(0, topMost.Count).Select(x => x.ToString())); int i = 0; foreach (var topNode in topMost) { string inputName = i.ToString(); node.ConnectInput(inputName, topNode.Item2.Build(buildDict, topNode.Item1)); i++; } top = node; } else top = topMost[0].Item2.BuildExpression(buildDict); // if the node has any outputs, we create a BeginNode in order to evaluate all of them // sequentially (begin evaluates a list of expressions) if (outputs.Any()) { var beginNode = new BeginNode(); List<dynNode> hangingNodes = functionWorkspace.GetTopMostNodes().ToList(); foreach (var tNode in hangingNodes.Select((x, index) => new { Index = index, Node = x })) { beginNode.AddInput(tNode.Index.ToString()); beginNode.ConnectInput(tNode.Index.ToString(), tNode.Node.Build(buildDict, 0)); } beginNode.AddInput(hangingNodes.Count.ToString()); beginNode.ConnectInput(hangingNodes.Count.ToString(), top); top = beginNode; } // make the anonymous function FScheme.Expression expression = Utils.MakeAnon(variables.Select(x => x.NodeUI.GUID.ToString()), top.Compile()); return expression; }
public FScheme.Expression Compile() { IEnumerable<string> inputNames = null; IEnumerable<string> outputNames = null; // Get the internal nodes for the function WorkspaceModel functionWorkspace = this.WorkspaceModel; #region Find outputs // Find output elements for the node List<Output> outputs = functionWorkspace.Nodes.OfType<Output>().ToList(); var topMost = new List<Tuple<int, NodeModel>>(); // if we found output nodes, add select their inputs // these will serve as the function output if (outputs.Any()) { topMost.AddRange( outputs.Where(x => x.HasInput(0)).Select(x => x.Inputs[0])); outputNames = outputs.Select(x => x.Symbol); } else { // if there are no explicitly defined output nodes // get the top most nodes and set THEM as the output IEnumerable<NodeModel> topMostNodes = functionWorkspace.GetTopMostNodes(); NodeModel infinite = null; var outNames = new List<string>(); foreach (NodeModel topNode in topMostNodes) { if (topNode is Function && (topNode as Function).Definition == this) { infinite = topNode; continue; } foreach (int output in Enumerable.Range(0, topNode.OutPortData.Count)) { if (!topNode.HasOutput(output)) { topMost.Add(Tuple.Create(output, topNode)); outNames.Add(topNode.OutPortData[output].NickName); } } } if (infinite != null && outNames.Count == 0) { topMost.Add(Tuple.Create(0, infinite)); outNames.Add("∞"); } outputNames = outNames; } #endregion // color the node to define its connectivity foreach (var ele in topMost) { ele.Item2.ValidateConnections(); } //Find function entry point, and then compile var variables = functionWorkspace.Nodes.OfType<Symbol>().ToList(); inputNames = variables.Select(x => x.InputSymbol); //Update existing function nodes which point to this function to match its changes dynSettings.Controller.DynamoModel.AllNodes .OfType<Function>() .Where(el => el.Definition != null && el.Definition.FunctionId == this.FunctionId) .ToList() .ForEach(node => { node.SetInputs(inputNames); node.SetOutputs(outputNames); node.RegisterAllPorts(); }); //Call OnSave for all saved elements functionWorkspace.Nodes.ToList().ForEach(x => x.onSave()); INode top; var buildDict = new Dictionary<NodeModel, Dictionary<int, INode>>(); if (topMost.Count > 1) { InputNode node = new ExternalFunctionNode(FScheme.Value.NewList); int i = 0; foreach (var topNode in topMost) { string inputName = i.ToString(CultureInfo.InvariantCulture); node.AddInput(inputName); node.ConnectInput(inputName, new BeginNode()); try { var exp = topNode.Item2.Build(buildDict, topNode.Item1); node.ConnectInput(inputName, exp); } catch { } i++; } top = node; } else if (topMost.Count == 1) { top = topMost[0].Item2.Build(buildDict, topMost[0].Item1); } else { // if the custom node is empty, it will initially be an empty begin top = new BeginNode(); } // if the node has any outputs, we create a BeginNode in order to evaluate all of them // sequentially (begin evaluates a list of expressions) if (outputs.Any()) { var beginNode = new BeginNode(); List<NodeModel> hangingNodes = functionWorkspace.GetHangingNodes().ToList(); foreach (var tNode in hangingNodes.Select((x, index) => new { Index = index, Node = x })) { beginNode.AddInput(tNode.Index.ToString(CultureInfo.InvariantCulture)); beginNode.ConnectInput( tNode.Index.ToString(CultureInfo.InvariantCulture), tNode.Node.Build(buildDict, 0)); } beginNode.AddInput(hangingNodes.Count.ToString(CultureInfo.InvariantCulture)); beginNode.ConnectInput(hangingNodes.Count.ToString(CultureInfo.InvariantCulture), top); top = beginNode; } // make the anonymous function FScheme.Expression expression = Utils.MakeAnon( variables.Select(x => x.GUID.ToString()), top.Compile()); return expression; }
public static FScheme.Expression CompileFunction(FunctionDefinition definition, ref IEnumerable <string> inputNames, ref IEnumerable <string> outputNames) { if (definition == null) { return(null); } // Get the internal nodes for the function dynWorkspaceModel functionWorkspace = definition.Workspace; #region Find outputs // Find output elements for the node List <dynOutput> outputs = functionWorkspace.Nodes.OfType <dynOutput>().ToList(); var topMost = new List <Tuple <int, dynNodeModel> >(); // if we found output nodes, add select their inputs // these will serve as the function output if (outputs.Any()) { topMost.AddRange( outputs.Where(x => x.HasInput(0)).Select(x => x.Inputs[0])); outputNames = outputs.Select(x => x.Symbol); } else { // if there are no explicitly defined output nodes // get the top most nodes and set THEM as the output IEnumerable <dynNodeModel> topMostNodes = functionWorkspace.GetTopMostNodes(); var outNames = new List <string>(); foreach (dynNodeModel topNode in topMostNodes) { foreach (int output in Enumerable.Range(0, topNode.OutPortData.Count)) { if (!topNode.HasOutput(output)) { topMost.Add(Tuple.Create(output, topNode)); outNames.Add(topNode.OutPortData[output].NickName); } } } outputNames = outNames; } #endregion // color the node to define its connectivity foreach (var ele in topMost) { ele.Item2.ValidateConnections(); } //Find function entry point, and then compile the function and add it to our environment IEnumerable <dynNodeModel> variables = functionWorkspace.Nodes.Where(x => x is dynSymbol); inputNames = variables.Select(x => (x as dynSymbol).Symbol); INode top; var buildDict = new Dictionary <dynNodeModel, Dictionary <int, INode> >(); if (topMost.Count > 1) { InputNode node = new ExternalFunctionNode(FScheme.Value.NewList); int i = 0; foreach (var topNode in topMost) { string inputName = i.ToString(); node.AddInput(inputName); node.ConnectInput(inputName, new BeginNode()); try { var exp = topNode.Item2.Build(buildDict, topNode.Item1); node.ConnectInput(inputName, exp); } catch { } i++; } top = node; } else if (topMost.Count == 1) { top = topMost[0].Item2.BuildExpression(buildDict); } else { // if the custom node is empty, it will initially be an empty begin top = new BeginNode(); } // if the node has any outputs, we create a BeginNode in order to evaluate all of them // sequentially (begin evaluates a list of expressions) if (outputs.Any()) { var beginNode = new BeginNode(); List <dynNodeModel> hangingNodes = functionWorkspace.GetHangingNodes().ToList(); foreach (var tNode in hangingNodes.Select((x, index) => new { Index = index, Node = x })) { beginNode.AddInput(tNode.Index.ToString()); beginNode.ConnectInput(tNode.Index.ToString(), tNode.Node.Build(buildDict, 0)); } beginNode.AddInput(hangingNodes.Count.ToString()); beginNode.ConnectInput(hangingNodes.Count.ToString(), top); top = beginNode; } // make the anonymous function FScheme.Expression expression = Utils.MakeAnon(variables.Select(x => x.GUID.ToString()), top.Compile()); return(expression); }
protected virtual void EvaluationThread(object s, DoWorkEventArgs args) { //Get our entry points (elements with nothing connected to output) List <dynNodeModel> topElements = DynamoViewModel.Model.HomeSpace.GetTopMostNodes().ToList(); //Mark the topmost as dirty/clean foreach (dynNodeModel topMost in topElements) { topMost.MarkDirty(); } //TODO: Flesh out error handling try { var topNode = new BeginNode(new List <string>()); int i = 0; var buildDict = new Dictionary <dynNodeModel, Dictionary <int, INode> >(); foreach (dynNodeModel topMost in topElements) { string inputName = i.ToString(); topNode.AddInput(inputName); topNode.ConnectInput(inputName, topMost.BuildExpression(buildDict)); i++; DynamoLogger.Instance.Log(topMost); } FScheme.Expression runningExpression = topNode.Compile(); Run(topElements, runningExpression); // inform any objects that a run has happened DynamoLogger.Instance.Log(runningExpression); } catch (CancelEvaluationException ex) { /* Evaluation was cancelled */ OnRunCancelled(false); //this.CancelRun = false; //Reset cancel flag RunCancelled = false; //If we are forcing this, then make sure we don't run again either. if (ex.Force) { runAgain = false; } OnRunCompleted(this, false); } catch (Exception ex) { /* Evaluation has an error */ //Catch unhandled exception if (ex.Message.Length > 0) { DynamoLogger.Instance.Log(ex); } OnRunCancelled(true); //Reset the flags runAgain = false; RunCancelled = false; OnRunCompleted(this, false); if (Testing) { Assert.Fail(ex.Message + ":" + ex.StackTrace); } } finally { /* Post-evaluation cleanup */ DynamoViewModel.RunEnabled = true; //No longer running Running = false; foreach (FunctionDefinition def in dynSettings.FunctionWasEvaluated) { def.RequiresRecalc = false; } //If we should run again... if (runAgain) { //DynamoLogger.Instance.Log("Running again."); //Reset flag runAgain = false; RunExpression(_showErrors); } else { //DynamoLogger.Instance.Log("Run completed."); OnRunCompleted(this, true); } } }
public FScheme.Expression Compile() { IEnumerable <string> inputNames = null; IEnumerable <string> outputNames = null; // Get the internal nodes for the function WorkspaceModel functionWorkspace = this.WorkspaceModel; #region Find outputs // Find output elements for the node List <Output> outputs = functionWorkspace.Nodes.OfType <Output>().ToList(); var topMost = new List <Tuple <int, NodeModel> >(); // if we found output nodes, add select their inputs // these will serve as the function output if (outputs.Any()) { topMost.AddRange( outputs.Where(x => x.HasInput(0)).Select(x => x.Inputs[0])); outputNames = outputs.Select(x => x.Symbol); } else { // if there are no explicitly defined output nodes // get the top most nodes and set THEM as the output IEnumerable <NodeModel> topMostNodes = functionWorkspace.GetTopMostNodes(); NodeModel infinite = null; var outNames = new List <string>(); foreach (NodeModel topNode in topMostNodes) { if (topNode is Function && (topNode as Function).Definition == this) { infinite = topNode; continue; } foreach (int output in Enumerable.Range(0, topNode.OutPortData.Count)) { if (!topNode.HasOutput(output)) { topMost.Add(Tuple.Create(output, topNode)); outNames.Add(topNode.OutPortData[output].NickName); } } } if (infinite != null && outNames.Count == 0) { topMost.Add(Tuple.Create(0, infinite)); outNames.Add("∞"); } outputNames = outNames; } #endregion // color the node to define its connectivity foreach (var ele in topMost) { ele.Item2.ValidateConnections(); } //Find function entry point, and then compile var variables = functionWorkspace.Nodes.OfType <Symbol>().ToList(); inputNames = variables.Select(x => x.InputSymbol); //Update existing function nodes which point to this function to match its changes dynSettings.Controller.DynamoModel.AllNodes .OfType <Function>() .Where(el => el.Definition != null && el.Definition.FunctionId == this.FunctionId) .ToList() .ForEach(node => { node.SetInputs(inputNames); node.SetOutputs(outputNames); node.RegisterAllPorts(); }); //Call OnSave for all saved elements functionWorkspace.Nodes.ToList().ForEach(x => x.onSave()); INode top; var buildDict = new Dictionary <NodeModel, Dictionary <int, INode> >(); if (topMost.Count > 1) { InputNode node = new ExternalFunctionNode(FScheme.Value.NewList); int i = 0; foreach (var topNode in topMost) { string inputName = i.ToString(CultureInfo.InvariantCulture); node.AddInput(inputName); node.ConnectInput(inputName, new BeginNode()); try { var exp = topNode.Item2.Build(buildDict, topNode.Item1); node.ConnectInput(inputName, exp); } catch { } i++; } top = node; } else if (topMost.Count == 1) { top = topMost[0].Item2.Build(buildDict, topMost[0].Item1); } else { // if the custom node is empty, it will initially be an empty begin top = new BeginNode(); } // if the node has any outputs, we create a BeginNode in order to evaluate all of them // sequentially (begin evaluates a list of expressions) if (outputs.Any()) { var beginNode = new BeginNode(); List <NodeModel> hangingNodes = functionWorkspace.GetHangingNodes().ToList(); foreach (var tNode in hangingNodes.Select((x, index) => new { Index = index, Node = x })) { beginNode.AddInput(tNode.Index.ToString(CultureInfo.InvariantCulture)); beginNode.ConnectInput( tNode.Index.ToString(CultureInfo.InvariantCulture), tNode.Node.Build(buildDict, 0)); } beginNode.AddInput(hangingNodes.Count.ToString(CultureInfo.InvariantCulture)); beginNode.ConnectInput(hangingNodes.Count.ToString(CultureInfo.InvariantCulture), top); top = beginNode; } // make the anonymous function FScheme.Expression expression = Utils.MakeAnon( variables.Select(x => x.GUID.ToString()), top.Compile()); return(expression); }
protected virtual void EvaluationThread(object s, DoWorkEventArgs args) { var sw = new Stopwatch(); sw.Start(); //Get our entry points (elements with nothing connected to output) List<NodeModel> topElements = DynamoViewModel.Model.HomeSpace.GetTopMostNodes().ToList(); //Mark the topmost as dirty/clean foreach (NodeModel topMost in topElements) { /* AstBuilder builder = AstBuilder.Instance; topMost.CompileToAstNode(builder); builder.Execute(); */ topMost.MarkDirty(); } try { var topNode = new BeginNode(new List<string>()); int i = 0; var buildDict = new Dictionary<NodeModel, Dictionary<int, INode>>(); foreach (NodeModel topMost in topElements) { string inputName = i.ToString(); topNode.AddInput(inputName); topNode.ConnectInput(inputName, topMost.BuildExpression(buildDict)); i++; //DynamoLogger.Instance.Log(topMost); } FScheme.Expression runningExpression = topNode.Compile(); Run(topElements, runningExpression); // inform any objects that a run has happened //DynamoLogger.Instance.Log(runningExpression); } catch (CancelEvaluationException ex) { /* Evaluation was cancelled */ OnRunCancelled(false); //this.CancelRun = false; //Reset cancel flag RunCancelled = false; //If we are forcing this, then make sure we don't run again either. if (ex.Force) runAgain = false; OnRunCompleted(this, false); } catch (Exception ex) { /* Evaluation has an error */ //Catch unhandled exception if (ex.Message.Length > 0) { DynamoLogger.Instance.Log(ex); } OnRunCancelled(true); //Reset the flags runAgain = false; RunCancelled = false; OnRunCompleted(this, false); if (Testing) Assert.Fail(ex.Message + ":" + ex.StackTrace); } finally { /* Post-evaluation cleanup */ DynamoViewModel.RunEnabled = true; //No longer running Running = false; foreach (FunctionDefinition def in dynSettings.FunctionWasEvaluated) def.RequiresRecalc = false; //If we should run again... if (runAgain) { //Reset flag runAgain = false; RunExpression(_showErrors); } else { OnRunCompleted(this, true); } sw.Stop(); DynamoLogger.Instance.Log(string.Format("Evaluation completed in {0}", sw.Elapsed.ToString())); } }
protected virtual void EvaluationThread(object s, DoWorkEventArgs args) { /* Execution Thread */ //Get our entry points (elements with nothing connected to output) IEnumerable <dynNodeModel> topElements = DynamoModel.HomeSpace.GetTopMostNodes(); //Mark the topmost as dirty/clean foreach (dynNodeModel topMost in topElements) { topMost.MarkDirty(); } //TODO: Flesh out error handling try { var topNode = new BeginNode(new List <string>()); var buildDict = new Dictionary <dynNodeModel, Dictionary <int, INode> >(); foreach (var topMost in topElements.Select((node, index) => new { node, index })) { string inputName = topMost.index.ToString(); topNode.AddInput(inputName); topNode.ConnectInput(inputName, topMost.node.BuildExpression(buildDict)); } FScheme.Expression runningExpression = topNode.Compile(); Run(DynamoModel.RunInDebug, topElements, runningExpression); } catch (CancelEvaluationException ex) { /* Evaluation was cancelled */ OnRunCancelled(false); //this.CancelRun = false; //Reset cancel flag RunCancelled = true; //If we are forcing this, then make sure we don't run again either. if (ex.Force) { runAgain = false; } OnRunCompleted(this, false); } catch (Exception ex) { /* Evaluation has an error */ //Catch unhandled exception if (ex.Message.Length > 0) { dynSettings.Controller.DynamoViewModel.Log(ex); } OnRunCancelled(true); //Reset the flags runAgain = false; RunCancelled = true; OnRunCompleted(this, false); } finally { /* Post-evaluation cleanup */ DynamoModel.RunEnabled = true; //No longer running Running = false; foreach (FunctionDefinition def in dynSettings.FunctionWasEvaluated) { def.RequiresRecalc = false; } //If we should run again... if (runAgain) { //Reset flag runAgain = false; if (dynSettings.Bench != null) { //Run this method again from the main thread dynSettings.Bench.Dispatcher.BeginInvoke( new Action(() => RunExpression(_showErrors))); } } else { OnRunCompleted(this, true); } } }
protected virtual void EvaluationThread(object s, DoWorkEventArgs args) { /* Execution Thread */ //Get our entry points (elements with nothing connected to output) IEnumerable<dynNodeModel> topElements = DynamoModel.HomeSpace.GetTopMostNodes(); //Mark the topmost as dirty/clean foreach (dynNodeModel topMost in topElements) topMost.MarkDirty(); //TODO: Flesh out error handling try { var topNode = new BeginNode(new List<string>()); int i = 0; var buildDict = new Dictionary<dynNodeModel, Dictionary<int, INode>>(); foreach (dynNodeModel topMost in topElements) { string inputName = i.ToString(); topNode.AddInput(inputName); topNode.ConnectInput(inputName, topMost.BuildExpression(buildDict)); i++; } FScheme.Expression runningExpression = topNode.Compile(); Run(DynamoModel.RunInDebug, topElements, runningExpression); } catch (CancelEvaluationException ex) { /* Evaluation was cancelled */ OnRunCancelled(false); //this.CancelRun = false; //Reset cancel flag RunCancelled = true; //If we are forcing this, then make sure we don't run again either. if (ex.Force) runAgain = false; OnRunCompleted(this, false); } catch (Exception ex) { /* Evaluation has an error */ //Catch unhandled exception if (ex.Message.Length > 0) { dynSettings.Controller.DynamoViewModel.Log(ex); } OnRunCancelled(true); //Reset the flags runAgain = false; RunCancelled = true; OnRunCompleted(this, false); } finally { /* Post-evaluation cleanup */ //Re-enable run button //dynSettings.Bench.Dispatcher.Invoke(new Action( // delegate // { // dynSettings.Bench.RunButton.IsEnabled = true; // } //)); DynamoModel.RunEnabled = true; //No longer running Running = false; foreach (FunctionDefinition def in dynSettings.FunctionWasEvaluated) def.RequiresRecalc = false; //If we should run again... if (runAgain) { //Reset flag runAgain = false; if (dynSettings.Bench != null) { //Run this method again from the main thread dynSettings.Bench.Dispatcher.BeginInvoke(new Action( delegate { RunExpression(_showErrors); } )); } } else { OnRunCompleted(this, true); } } }
/// <summary> /// Save a function. This includes writing to a file and compiling the /// function and saving it to the FSchemeEnvironment /// </summary> /// <param name="definition">The definition to saveo</param> /// <param name="bool">Whether to write the function to file</param> /// <returns>Whether the operation was successful</returns> public void SaveFunction(FunctionDefinition definition, bool writeDefinition = true) { if (definition == null) return; // Get the internal nodes for the function dynWorkspace functionWorkspace = definition.Workspace; // If asked to, write the definition to file if (writeDefinition) { string directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string pluginsPath = Path.Combine(directory, "definitions"); try { if (!Directory.Exists(pluginsPath)) Directory.CreateDirectory(pluginsPath); string path = Path.Combine(pluginsPath, FormatFileName(functionWorkspace.Name) + ".dyf"); SaveWorkspace(path, functionWorkspace, definition.FunctionId); } catch (Exception e) { Bench.Log("Error saving:" + e.GetType()); Bench.Log(e); } } try { #region Find outputs // Find output elements for the node IEnumerable<dynNode> outputs = functionWorkspace.Nodes.Where(x => x is dynOutput); var topMost = new List<Tuple<int, dynNode>>(); IEnumerable<string> outputNames; // if we found output nodes, add select their inputs // these will serve as the function output if (outputs.Any()) { topMost.AddRange( outputs.Where(x => x.HasInput(0)).Select(x => x.Inputs[0])); outputNames = outputs.Select(x => (x as dynOutput).Symbol); } else { // if there are no explicitly defined output nodes // get the top most nodes and set THEM as tht output IEnumerable<dynNode> topMostNodes = functionWorkspace.GetTopMostNodes(); var outNames = new List<string>(); foreach (dynNode topNode in topMostNodes) { foreach (int output in Enumerable.Range(0, topNode.OutPortData.Count)) { if (!topNode.HasOutput(output)) { topMost.Add(Tuple.Create(output, topNode)); outNames.Add(topNode.OutPortData[output].NickName); } } } outputNames = outNames; } #endregion // color the node to define its connectivity foreach (var ele in topMost) { ele.Item2.NodeUI.ValidateConnections(); } //Find function entry point, and then compile the function and add it to our environment IEnumerable<dynNode> variables = functionWorkspace.Nodes.Where(x => x is dynSymbol); IEnumerable<string> inputNames = variables.Select(x => (x as dynSymbol).Symbol); INode top; var buildDict = new Dictionary<dynNode, Dictionary<int, INode>>(); if (topMost.Count > 1) { InputNode node = new ExternalFunctionNode( FScheme.Value.NewList, Enumerable.Range(0, topMost.Count).Select(x => x.ToString())); int i = 0; foreach (var topNode in topMost) { string inputName = i.ToString(); node.ConnectInput(inputName, topNode.Item2.Build(buildDict, topNode.Item1)); i++; } top = node; } else top = topMost[0].Item2.BuildExpression(buildDict); // if the node has any outputs, we create a BeginNode in order to evaluate all of them // sequentially (begin evaluates a list of expressions) if (outputs.Any()) { var beginNode = new BeginNode(); List<dynNode> hangingNodes = functionWorkspace.GetTopMostNodes().ToList(); foreach (var tNode in hangingNodes.Select((x, index) => new {Index = index, Node = x})) { beginNode.AddInput(tNode.Index.ToString()); beginNode.ConnectInput(tNode.Index.ToString(), tNode.Node.Build(buildDict, 0)); } beginNode.AddInput(hangingNodes.Count.ToString()); beginNode.ConnectInput(hangingNodes.Count.ToString(), top); top = beginNode; } // make the anonymous function FScheme.Expression expression = Utils.MakeAnon(variables.Select(x => x.NodeUI.GUID.ToString()), top.Compile()); // make it accessible in the FScheme environment FSchemeEnvironment.DefineSymbol(definition.FunctionId.ToString(), expression); //Update existing function nodes which point to this function to match its changes foreach (dynNode el in AllNodes) { if (el is dynFunction) { var node = (dynFunction) el; if (node.Definition != definition) continue; node.SetInputs(inputNames); node.SetOutputs(outputNames); el.NodeUI.RegisterAllPorts(); } } //Call OnSave for all saved elements foreach (dynNode el in functionWorkspace.Nodes) el.onSave(); } catch (Exception ex) { Bench.Log(ex.GetType() + ": " + ex.Message); } }
public void SaveFunction(dynWorkspace functionWorkspace, bool writeDefinition = true) { //Generate xml, and save it in a fixed place if (writeDefinition) { string directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string pluginsPath = Path.Combine(directory, "definitions"); try { if (!Directory.Exists(pluginsPath)) Directory.CreateDirectory(pluginsPath); string path = Path.Combine(pluginsPath, FormatFileName(functionWorkspace.Name) + ".dyf"); SaveWorkspace(path, functionWorkspace); } catch (Exception e) { Bench.Log("Error saving:" + e.GetType()); Bench.Log(e); } } try { var outputs = functionWorkspace.Nodes.Where(x => x is dynOutput); var topMost = new List<Tuple<int, dynNode>>(); IEnumerable<string> outputNames; if (outputs.Any()) { topMost.AddRange( outputs.Where(x => x.HasInput(0)).Select(x => x.Inputs[0])); outputNames = outputs.Select(x => (x as dynOutput).Symbol); } else { var topMostNodes = functionWorkspace.GetTopMostNodes(); var outNames = new List<string>(); foreach (var topNode in topMostNodes) { foreach (var output in Enumerable.Range(0, topNode.OutPortData.Count)) { if (!topNode.HasOutput(output)) { topMost.Add(Tuple.Create(output, topNode)); outNames.Add(topNode.OutPortData[output].NickName); } } } outputNames = outNames; } foreach (var ele in topMost) { ele.Item2.NodeUI.ValidateConnections(); } //Find function entry point, and then compile the function and add it to our environment //dynNode top = topMost.FirstOrDefault(); var variables = functionWorkspace.Nodes.Where(x => x is dynSymbol); var inputNames = variables.Select(x => (x as dynSymbol).Symbol); INode top; var buildDict = new Dictionary<dynNode, Dictionary<int, INode>>(); if (topMost.Count > 1) { InputNode node = new ExternalFunctionNode( FScheme.Value.NewList, Enumerable.Range(0, topMost.Count).Select(x => x.ToString())); var i = 0; foreach (var topNode in topMost) { var inputName = i.ToString(); node.ConnectInput(inputName, topNode.Item2.Build(buildDict, topNode.Item1)); i++; } top = node; } else top = topMost[0].Item2.BuildExpression(buildDict); if (outputs.Any()) { var beginNode = new BeginNode(); var hangingNodes = functionWorkspace.GetTopMostNodes().ToList(); foreach (var tNode in hangingNodes.Select((x, index) => new { Index = index, Node = x })) { beginNode.AddInput(tNode.Index.ToString()); beginNode.ConnectInput(tNode.Index.ToString(), tNode.Node.Build(buildDict, 0)); } beginNode.AddInput(hangingNodes.Count.ToString()); beginNode.ConnectInput(hangingNodes.Count.ToString(), top); top = beginNode; } Expression expression = Utils.MakeAnon(variables.Select(x => x.NodeUI.GUID.ToString()), top.Compile()); FSchemeEnvironment.DefineSymbol(functionWorkspace.Name, expression); //Update existing function nodes which point to this function to match its changes foreach (var el in this.AllNodes) { if (el is dynFunction) { var node = (dynFunction)el; if (!node.Symbol.Equals(functionWorkspace.Name)) continue; node.SetInputs(inputNames); node.SetOutputs(outputNames); el.NodeUI.RegisterAllPorts(); } } //Call OnSave for all saved elements foreach (var el in functionWorkspace.Nodes) el.onSave(); //Update new add menu var addItem = (dynFunction)Bench.addMenuItemsDictNew[functionWorkspace.Name].NodeLogic; addItem.SetInputs(inputNames); addItem.SetOutputs(outputNames); addItem.NodeUI.RegisterAllPorts(); addItem.NodeUI.State = ElementState.DEAD; } catch (Exception ex) { Bench.Log(ex.GetType().ToString() + ": " + ex.Message); } }
protected virtual void EvaluationThread(object s, DoWorkEventArgs args) { /* Execution Thread */ //Get our entry points (elements with nothing connected to output) var topElements = homeSpace.GetTopMostNodes(); //Mark the topmost as dirty/clean foreach (var topMost in topElements) topMost.MarkDirty(); //TODO: Flesh out error handling try { var topNode = new BeginNode(new List<string>()); var i = 0; var buildDict = new Dictionary<dynNode, Dictionary<int, INode>>(); foreach (var topMost in topElements) { var inputName = i.ToString(); topNode.AddInput(inputName); topNode.ConnectInput(inputName, topMost.BuildExpression(buildDict)); i++; } Expression runningExpression = topNode.Compile(); Run(topElements, runningExpression); } catch (CancelEvaluationException ex) { /* Evaluation was cancelled */ OnRunCancelled(false); //this.CancelRun = false; //Reset cancel flag this.RunCancelled = true; //If we are forcing this, then make sure we don't run again either. if (ex.Force) this.runAgain = false; } catch (Exception ex) { /* Evaluation has an error */ //Catch unhandled exception if (ex.Message.Length > 0) { Bench.Dispatcher.Invoke(new Action( delegate { Bench.Log(ex); } )); } OnRunCancelled(true); //Reset the flags this.runAgain = false; this.RunCancelled = true; } finally { /* Post-evaluation cleanup */ //Re-enable run button Bench.Dispatcher.Invoke(new Action( delegate { Bench.RunButton.IsEnabled = true; } )); //No longer running this.Running = false; //If we should run again... if (this.runAgain) { //Reset flag this.runAgain = false; //Run this method again from the main thread Bench.Dispatcher.BeginInvoke(new Action( delegate { RunExpression(_debug, _showErrors); } )); } } }