protected override void Run(List <NodeModel> topElements, FScheme.Expression runningExpression) { var model = (DynamoRevitViewModel)DynamoViewModel; //If we are not running in debug... if (!DynamoViewModel.RunInDebug) { //Do we need manual transaction control? bool manualTrans = topElements.Any(CheckManualTransaction.TraverseUntilAny); //Can we avoid running everything in the Revit Idle thread? bool noIdleThread = manualTrans || !topElements.Any(CheckRequiresTransaction.TraverseUntilAny); //If we don't need to be in the idle thread... if (noIdleThread || IsTestMode) { //DynamoLogger.Instance.Log("Running expression in evaluation thread..."); TransMode = TransactionMode.Manual; //Manual transaction control if (IsTestMode) { TransMode = TransactionMode.Automatic; } InIdleThread = false; //Not in idle thread at the moment base.Run(topElements, runningExpression); //Just run the Run Delegate } else //otherwise... { //DynamoLogger.Instance.Log("Running expression in Revit's Idle thread..."); TransMode = TransactionMode.Automatic; //Automatic transaction control Debug.WriteLine("Adding a run to the idle stack."); InIdleThread = true; //Now in the idle thread. IdlePromise.ExecuteOnIdle( () => base.Run(topElements, runningExpression), false); //Execute the Run Delegate in the Idle thread. } } else //If we are in debug mode... { TransMode = TransactionMode.Debug; //Debug transaction control InIdleThread = true; //Everything will be evaluated in the idle thread. DynamoLogger.Instance.Log("Running expression in debug."); //Execute the Run Delegate. base.Run(topElements, runningExpression); } }
protected override void Run(IEnumerable <dynNodeModel> topElements, FScheme.Expression runningExpression) { //If we are not running in debug... if (!this.DynamoViewModel.RunInDebug) { //Do we need manual transaction control? bool manualTrans = topElements.Any((DynamoViewModel as DynamoRevitViewModel).CheckManualTransaction.TraverseUntilAny); //Can we avoid running everything in the Revit Idle thread? bool noIdleThread = manualTrans || !topElements.Any((DynamoViewModel as DynamoRevitViewModel).CheckRequiresTransaction.TraverseUntilAny); //If we don't need to be in the idle thread... if (noIdleThread || this.Testing) { DynamoLogger.Instance.Log("Running expression in evaluation thread..."); (DynamoViewModel as DynamoRevitViewModel).TransMode = DynamoRevitViewModel.TransactionMode.Manual; //Manual transaction control if (this.Testing) { (DynamoViewModel as DynamoRevitViewModel).TransMode = DynamoRevitViewModel.TransactionMode.Automatic; } this.InIdleThread = false; //Not in idle thread at the moment base.Run(topElements, runningExpression); //Just run the Run Delegate } else //otherwise... { DynamoLogger.Instance.Log("Running expression in Revit's Idle thread..."); (DynamoViewModel as DynamoRevitViewModel).TransMode = DynamoRevitViewModel.TransactionMode.Automatic; //Automatic transaction control Debug.WriteLine("Adding a run to the idle stack."); this.InIdleThread = true; //Now in the idle thread. IdlePromise.ExecuteOnIdle(new Action( () => base.Run(topElements, runningExpression)), false); //Execute the Run Delegate in the Idle thread. } } else //If we are in debug mode... { (DynamoViewModel as DynamoRevitViewModel).TransMode = DynamoRevitViewModel.TransactionMode.Debug; //Debug transaction control this.InIdleThread = true; //Everything will be evaluated in the idle thread. dynSettings.Controller.DynamoViewModel.Log("Running expression in debug."); //Execute the Run Delegate. base.Run(topElements, runningExpression); } }
public void Log(FScheme.Expression expression) { Log(FScheme.printExpression("\t", expression)); }
protected virtual void Run(List <dynNodeModel> topElements, FScheme.Expression runningExpression) { //Print some stuff if we're in debug mode if (DynamoViewModel.RunInDebug) { if (dynSettings.Controller.UIDispatcher != null) { foreach (string exp in topElements.Select(node => node.PrintExpression())) { DynamoLogger.Instance.Log("> " + exp); } } } try { DynamoLogger.Instance.Log("Evaluating the expression..."); //Evaluate the expression FScheme.Value expr = FSchemeEnvironment.Evaluate(runningExpression); if (dynSettings.Controller.UIDispatcher != null) { //Print some more stuff if we're in debug mode if (DynamoViewModel.RunInDebug && expr != null) { DynamoLogger.Instance.Log(FScheme.print(expr)); } } } catch (CancelEvaluationException ex) { /* Evaluation was cancelled */ OnRunCancelled(false); RunCancelled = false; if (ex.Force) { runAgain = false; } } catch (Exception ex) { /* Evaluation failed due to error */ if (dynSettings.Controller.UIDispatcher != null) { //Print unhandled exception if (ex.Message.Length > 0) { dynSettings.Controller.DispatchOnUIThread(() => DynamoLogger.Instance.Log(ex)); } } OnRunCancelled(true); RunCancelled = true; runAgain = false; //If we are testing, we need to throw an exception here //which will, in turn, throw an Assert.Fail in the //Evaluation thread. if (Testing) { throw new Exception(ex.Message); } } OnEvaluationCompleted(); }
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); } } }
/// <summary> /// Deserialize a function definition from a given path. A side effect of this function is that /// the node is added to the dictionary of loadedNodes. /// </summary> /// <param name="funcDefGuid">The function guid we're currently loading</param> /// <param name="controller">Reference to the calling controller</param> /// <param name="def">The resultant function definition</param> /// <returns></returns> private bool GetDefinitionFromPath(Guid funcDefGuid, out FunctionDefinition def) { var controller = dynSettings.Controller; try { var xmlPath = GetNodePath(funcDefGuid); #region read xml file var xmlDoc = new XmlDocument(); xmlDoc.Load(xmlPath); string funName = null; string category = ""; double cx = 0; double cy = 0; string description = ""; string version = ""; double zoom = 1.0; string id = ""; // load the header // handle legacy workspace nodes called dynWorkspace // and new workspaces without the dyn prefix XmlNodeList workspaceNodes = xmlDoc.GetElementsByTagName("Workspace"); if (workspaceNodes.Count == 0) { workspaceNodes = xmlDoc.GetElementsByTagName("dynWorkspace"); } foreach (XmlNode node in workspaceNodes) { foreach (XmlAttribute att in node.Attributes) { if (att.Name.Equals("X")) { cx = double.Parse(att.Value, CultureInfo.InvariantCulture); } else if (att.Name.Equals("Y")) { cy = double.Parse(att.Value, CultureInfo.InvariantCulture); } else if (att.Name.Equals("zoom")) { zoom = double.Parse(att.Value, CultureInfo.InvariantCulture); } else if (att.Name.Equals("Name")) { funName = att.Value; } else if (att.Name.Equals("Category")) { category = att.Value; } else if (att.Name.Equals("Description")) { description = att.Value; } else if (att.Name.Equals("ID")) { id = att.Value; } else if (att.Name.Equals("Version")) { version = att.Value; } } } // we have a dyf and it lacks an ID field, we need to assign it // a deterministic guid based on its name. By doing it deterministically, // files remain compatible if (string.IsNullOrEmpty(id) && !string.IsNullOrEmpty(funName)) { id = GuidUtility.Create(GuidUtility.UrlNamespace, funName).ToString(); } #endregion //DynamoCommands.WriteToLogCmd.Execute("Loading node definition for \"" + funName + "\" from: " + xmlPath); dynSettings.Controller.DynamoModel.WriteToLog("Loading node definition for \"" + funName + "\" from: " + xmlPath); var ws = new CustomNodeWorkspaceModel( funName, category.Length > 0 ? category : "Custom Nodes", description, cx, cy) { WatchChanges = false, FileName = xmlPath, Zoom = zoom }; def = new FunctionDefinition(Guid.Parse(id)) { WorkspaceModel = ws }; // load a dummy version, so any nodes depending on this node // will find an (empty) identifier on compilation FScheme.Expression dummyExpression = FScheme.Expression.NewNumber_E(0); controller.FSchemeEnvironment.DefineSymbol(def.FunctionId.ToString(), dummyExpression); // set the node as loaded this.LoadedCustomNodes.Add(def.FunctionId, def); XmlNodeList elNodes = xmlDoc.GetElementsByTagName("Elements"); XmlNodeList cNodes = xmlDoc.GetElementsByTagName("Connectors"); XmlNodeList nNodes = xmlDoc.GetElementsByTagName("Notes"); if (elNodes.Count == 0) { elNodes = xmlDoc.GetElementsByTagName("dynElements"); } if (cNodes.Count == 0) { cNodes = xmlDoc.GetElementsByTagName("dynConnectors"); } if (nNodes.Count == 0) { nNodes = xmlDoc.GetElementsByTagName("dynNotes"); } XmlNode elNodesList = elNodes[0]; XmlNode cNodesList = cNodes[0]; XmlNode nNodesList = nNodes[0]; #region instantiate nodes var badNodes = new List <Guid>(); foreach (XmlNode elNode in elNodesList.ChildNodes) { XmlAttribute typeAttrib = elNode.Attributes["type"]; XmlAttribute guidAttrib = elNode.Attributes["guid"]; XmlAttribute nicknameAttrib = elNode.Attributes["nickname"]; XmlAttribute xAttrib = elNode.Attributes["x"]; XmlAttribute yAttrib = elNode.Attributes["y"]; XmlAttribute lacingAttrib = elNode.Attributes["lacing"]; XmlAttribute isVisAttrib = elNode.Attributes["isVisible"]; XmlAttribute isUpstreamVisAttrib = elNode.Attributes["isUpstreamVisible"]; string typeName = typeAttrib.Value; //test the GUID to confirm that it is non-zero //if it is zero, then we have to fix it //this will break the connectors, but it won't keep //propagating bad GUIDs var guid = new Guid(guidAttrib.Value); if (guid == Guid.Empty) { guid = Guid.NewGuid(); } string nickname = nicknameAttrib.Value; double x = double.Parse(xAttrib.Value, CultureInfo.InvariantCulture); double y = double.Parse(yAttrib.Value, CultureInfo.InvariantCulture); bool isVisible = true; if (isVisAttrib != null) { isVisible = isVisAttrib.Value == "true" ? true : false; } bool isUpstreamVisible = true; if (isUpstreamVisAttrib != null) { isUpstreamVisible = isUpstreamVisAttrib.Value == "true" ? true : false; } typeName = Dynamo.Nodes.Utilities.PreprocessTypeName(typeName); System.Type type = Dynamo.Nodes.Utilities.ResolveType(typeName); if (null == type) { badNodes.Add(guid); continue; } NodeModel el = dynSettings.Controller.DynamoModel.CreateNodeInstance(type, nickname, guid); if (lacingAttrib != null) { LacingStrategy lacing = LacingStrategy.First; Enum.TryParse(lacingAttrib.Value, out lacing); el.ArgumentLacing = lacing; } el.IsVisible = isVisible; el.IsUpstreamVisible = isUpstreamVisible; ws.Nodes.Add(el); el.WorkSpace = ws; var node = el; node.X = x; node.Y = y; if (el == null) { return(false); } el.DisableReporting(); el.Load( elNode, string.IsNullOrEmpty(version) ? new Version(0, 0, 0, 0) : new Version(version)); } #endregion #region instantiate connectors foreach (XmlNode connector in cNodesList.ChildNodes) { XmlAttribute guidStartAttrib = connector.Attributes[0]; XmlAttribute intStartAttrib = connector.Attributes[1]; XmlAttribute guidEndAttrib = connector.Attributes[2]; XmlAttribute intEndAttrib = connector.Attributes[3]; XmlAttribute portTypeAttrib = connector.Attributes[4]; var guidStart = new Guid(guidStartAttrib.Value); var guidEnd = new Guid(guidEndAttrib.Value); int startIndex = Convert.ToInt16(intStartAttrib.Value); int endIndex = Convert.ToInt16(intEndAttrib.Value); PortType portType = ((PortType)Convert.ToInt16(portTypeAttrib.Value)); //find the elements to connect NodeModel start = null; NodeModel end = null; if (badNodes.Contains(guidStart) || badNodes.Contains(guidEnd)) { continue; } foreach (NodeModel e in ws.Nodes) { if (e.GUID == guidStart) { start = e; } else if (e.GUID == guidEnd) { end = e; } if (start != null && end != null) { break; } } try { var newConnector = ConnectorModel.Make( start, end, startIndex, endIndex, portType); if (newConnector != null) { ws.Connectors.Add(newConnector); } } catch { //DynamoCommands.WriteToLogCmd.Execute(string.Format("ERROR : Could not create connector between {0} and {1}.", start.NickName, end.NickName)); dynSettings.Controller.DynamoModel.WriteToLog(string.Format("ERROR : Could not create connector between {0} and {1}.", start.NickName, end.NickName)); } } #endregion #region instantiate notes if (nNodesList != null) { foreach (XmlNode note in nNodesList.ChildNodes) { XmlAttribute textAttrib = note.Attributes[0]; XmlAttribute xAttrib = note.Attributes[1]; XmlAttribute yAttrib = note.Attributes[2]; string text = textAttrib.Value; double x = Convert.ToDouble(xAttrib.Value, CultureInfo.InvariantCulture); double y = Convert.ToDouble(yAttrib.Value, CultureInfo.InvariantCulture); Guid guid = Guid.NewGuid(); var command = new DynCmd.CreateNoteCommand(guid, text, x, y, false); dynSettings.Controller.DynamoModel.AddNoteInternal(command, ws); } } #endregion foreach (var e in ws.Nodes) { e.EnableReporting(); } def.CompileAndAddToEnvironment(controller.FSchemeEnvironment); ws.WatchChanges = true; this.OnGetDefinitionFromPath(def); } catch (Exception ex) { dynSettings.Controller.DynamoModel.WriteToLog("There was an error opening the workbench."); dynSettings.Controller.DynamoModel.WriteToLog(ex); if (DynamoController.IsTestMode) { Assert.Fail(ex.Message); } def = null; return(false); } return(true); }
/// <summary> /// Deserialize a function definition from a given path. A side effect of this function is that /// the node is added to the dictionary of loadedNodes. /// </summary> /// <param name="funcDefGuid">The function guid we're currently loading</param> /// <param name="controller">Reference to the calling controller</param> /// <param name="def">The resultant function definition</param> /// <returns></returns> private bool GetDefinitionFromPath(Guid funcDefGuid, DynamoController controller, out FunctionDefinition def) { try { var xmlPath = GetNodePath(funcDefGuid); #region read xml file var xmlDoc = new XmlDocument(); xmlDoc.Load(xmlPath); string funName = null; string category = ""; string description = ""; double cx = DynamoView.CANVAS_OFFSET_X; double cy = DynamoView.CANVAS_OFFSET_Y; double zoom = 1.0; string id = ""; // load the header foreach (XmlNode node in xmlDoc.GetElementsByTagName("dynWorkspace")) { foreach (XmlAttribute att in node.Attributes) { if (att.Name.Equals("X")) { cx = double.Parse(att.Value, CultureInfo.InvariantCulture); } else if (att.Name.Equals("Y")) { cy = double.Parse(att.Value, CultureInfo.InvariantCulture); } else if (att.Name.Equals("zoom")) { zoom = double.Parse(att.Value, CultureInfo.InvariantCulture); } else if (att.Name.Equals("Name")) { funName = att.Value; } else if (att.Name.Equals("Category")) { category = att.Value; } else if (att.Name.Equals("Description")) { description = att.Value; } else if (att.Name.Equals("ID")) { id = att.Value; } } } // we have a dyf and it lacks an ID field, we need to assign it // a deterministic guid based on its name. By doing it deterministically, // files remain compatible if (string.IsNullOrEmpty(id) && !string.IsNullOrEmpty(funName)) { id = GuidUtility.Create(GuidUtility.UrlNamespace, funName).ToString(); } #endregion DynamoCommands.WriteToLogCmd.Execute("Loading node definition for \"" + funName + "\" from: " + xmlPath); var ws = new FuncWorkspace( funName, category.Length > 0 ? category : BuiltinNodeCategories.SCRIPTING_CUSTOMNODES, description, cx, cy) { WatchChanges = false }; ws.Zoom = zoom; def = new FunctionDefinition(Guid.Parse(id)) { Workspace = ws }; // load a dummy version, so any nodes depending on this node // will find an (empty) identifier on compilation FScheme.Expression dummyExpression = FScheme.Expression.NewNumber_E(0); controller.FSchemeEnvironment.DefineSymbol(def.FunctionId.ToString(), dummyExpression); this.loadedNodes.Add(def.FunctionId, def); XmlNodeList elNodes = xmlDoc.GetElementsByTagName("dynElements"); XmlNodeList cNodes = xmlDoc.GetElementsByTagName("dynConnectors"); XmlNodeList nNodes = xmlDoc.GetElementsByTagName("dynNotes"); XmlNode elNodesList = elNodes[0]; XmlNode cNodesList = cNodes[0]; XmlNode nNodesList = nNodes[0]; #region instantiate nodes var badNodes = new List <Guid>(); foreach (XmlNode elNode in elNodesList.ChildNodes) { XmlAttribute typeAttrib = elNode.Attributes["type"]; XmlAttribute guidAttrib = elNode.Attributes["guid"]; XmlAttribute nicknameAttrib = elNode.Attributes["nickname"]; XmlAttribute xAttrib = elNode.Attributes["x"]; XmlAttribute yAttrib = elNode.Attributes["y"]; XmlAttribute lacingAttrib = elNode.Attributes["lacing"]; XmlAttribute isVisAttrib = elNode.Attributes["isVisible"]; XmlAttribute isUpstreamVisAttrib = elNode.Attributes["isUpstreamVisible"]; string typeName = typeAttrib.Value; const string oldNamespace = "Dynamo.Elements."; if (typeName.StartsWith(oldNamespace)) { typeName = "Dynamo.Nodes." + typeName.Remove(0, oldNamespace.Length); } //test the GUID to confirm that it is non-zero //if it is zero, then we have to fix it //this will break the connectors, but it won't keep //propagating bad GUIDs var guid = new Guid(guidAttrib.Value); if (guid == Guid.Empty) { guid = Guid.NewGuid(); } string nickname = nicknameAttrib.Value; double x = double.Parse(xAttrib.Value, CultureInfo.InvariantCulture); double y = double.Parse(yAttrib.Value, CultureInfo.InvariantCulture); bool isVisible = true; if (isVisAttrib != null) { isVisible = isVisAttrib.Value == "true" ? true : false; } bool isUpstreamVisible = true; if (isUpstreamVisAttrib != null) { isUpstreamVisible = isUpstreamVisAttrib.Value == "true" ? true : false; } //Type t = Type.GetType(typeName); TypeLoadData tData; Type t; if (!controller.BuiltInTypesByName.TryGetValue(typeName, out tData)) { //try and get a system type by this name t = Type.GetType(typeName); //if we still can't find the type, try the also known as attributes if (t == null) { //try to get the also known as values foreach (KeyValuePair <string, TypeLoadData> kvp in controller.BuiltInTypesByName) { var akaAttribs = kvp.Value.Type.GetCustomAttributes(typeof(AlsoKnownAsAttribute), false); if (akaAttribs.Any()) { if ((akaAttribs[0] as AlsoKnownAsAttribute).Values.Contains(typeName)) { controller.DynamoViewModel.Log(string.Format("Found matching node for {0} also known as {1}", kvp.Key, typeName)); t = kvp.Value.Type; } } } } if (t == null) { controller.DynamoViewModel.Log("Could not load node of type: " + typeName); controller.DynamoViewModel.Log("Loading will continue but nodes might be missing from your workflow."); //return false; badNodes.Add(guid); continue; } } else { t = tData.Type; } dynNodeModel el = dynSettings.Controller.DynamoViewModel.CreateNodeInstance(t, nickname, guid); if (lacingAttrib != null) { LacingStrategy lacing = LacingStrategy.First; Enum.TryParse(lacingAttrib.Value, out lacing); el.ArgumentLacing = lacing; } el.IsVisible = isVisible; el.IsUpstreamVisible = isUpstreamVisible; // note - this is because the connectors fail to be created if there's not added // to the canvas ws.Nodes.Add(el); el.WorkSpace = ws; var node = el; node.X = x; node.Y = y; if (el == null) { return(false); } el.DisableReporting(); el.Load(elNode); // inject the node properties from the xml // moved this logic to LoadNode in dynFunction --SJE //if (el is dynFunction) //{ // var fun = el as dynFunction; // // we've found a custom node, we need to attempt to load its guid. // // if it doesn't exist (i.e. its a legacy node), we need to assign it one, // // deterministically // Guid funId; // try // { // funId = Guid.Parse(fun.Symbol); // } // catch // { // funId = GuidUtility.Create(GuidUtility.UrlNamespace, nicknameAttrib.Value); // fun.Symbol = funId.ToString(); // } // // if it's not a recurisve node and it's not yet loaded, load it // if (funcDefGuid != funId && !this.loadedNodes.ContainsKey(funId)) // { // dynSettings.Controller.CustomNodeLoader.GetFunctionDefinition(funId); // fun.Definition = this.loadedNodes[funId]; // } // else if ( this.loadedNodes.ContainsKey(funId )) // { // fun.Definition = this.loadedNodes[funId]; // } //} } #endregion #region instantiate connectors foreach (XmlNode connector in cNodesList.ChildNodes) { XmlAttribute guidStartAttrib = connector.Attributes[0]; XmlAttribute intStartAttrib = connector.Attributes[1]; XmlAttribute guidEndAttrib = connector.Attributes[2]; XmlAttribute intEndAttrib = connector.Attributes[3]; XmlAttribute portTypeAttrib = connector.Attributes[4]; var guidStart = new Guid(guidStartAttrib.Value); var guidEnd = new Guid(guidEndAttrib.Value); int startIndex = Convert.ToInt16(intStartAttrib.Value); int endIndex = Convert.ToInt16(intEndAttrib.Value); int portType = Convert.ToInt16(portTypeAttrib.Value); //find the elements to connect dynNodeModel start = null; dynNodeModel end = null; if (badNodes.Contains(guidStart) || badNodes.Contains(guidEnd)) { continue; } foreach (dynNodeModel e in ws.Nodes) { if (e.GUID == guidStart) { start = e; } else if (e.GUID == guidEnd) { end = e; } if (start != null && end != null) { break; } } try { var newConnector = dynConnectorModel.Make( start, end, startIndex, endIndex, portType); if (newConnector != null) { ws.Connectors.Add(newConnector); } } catch { DynamoCommands.WriteToLogCmd.Execute(string.Format("ERROR : Could not create connector between {0} and {1}.", start.NickName, end.NickName)); } } #endregion #region instantiate notes if (nNodesList != null) { foreach (XmlNode note in nNodesList.ChildNodes) { XmlAttribute textAttrib = note.Attributes[0]; XmlAttribute xAttrib = note.Attributes[1]; XmlAttribute yAttrib = note.Attributes[2]; string text = textAttrib.Value; double x = Convert.ToDouble(xAttrib.Value); double y = Convert.ToDouble(yAttrib.Value); //dynNoteView n = Bench.AddNote(text, x, y, ws); //Bench.AddNote(text, x, y, ws); var paramDict = new Dictionary <string, object>(); paramDict.Add("x", x); paramDict.Add("y", y); paramDict.Add("text", text); paramDict.Add("workspace", ws); dynSettings.Controller.DynamoViewModel.AddNoteCommand.Execute(paramDict); } } #endregion foreach (dynNodeModel e in ws.Nodes) { e.EnableReporting(); } ws.FilePath = xmlPath; var expression = CompileFunction(def); controller.FSchemeEnvironment.DefineSymbol(def.FunctionId.ToString(), expression); ws.WatchChanges = true; } catch (Exception ex) { DynamoCommands.WriteToLogCmd.Execute("There was an error opening the workbench."); DynamoCommands.WriteToLogCmd.Execute(ex); if (controller.Testing) { Assert.Fail(ex.Message); } def = null; return(false); } return(true); }
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); }
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); }
/// <summary> /// Log an expression /// </summary> /// <param name="expression"></param> public void Log(FScheme.Expression expression) { Instance.Log(FScheme.printExpression("\t", expression), LogLevel.Console); }
protected internal virtual void Run(bool runInDebug, IEnumerable <dynNodeModel> topElements, FScheme.Expression runningExpression) { //Print some stuff if we're in debug mode if (runInDebug) { // NOPE //if (dynSettings.Bench != null) //{ // //string exp = FScheme.print(runningExpression); // //dynSettings.Bench.Dispatcher.Invoke(new Action( // // delegate // // { // // foreach (dynNodeModel node in topElements) // // { // // string exp = node.PrintExpression(); // // dynSettings.Controller.DynamoViewModel.Log("> " + exp); // // } // // } // // )); //} } try { //Evaluate the expression FScheme.Value expr = this.FSchemeEnv.Evaluate(runningExpression); if (dynSettings.Bench != null) { //Print some more stuff if we're in debug mode if (runInDebug && expr != null) { // NOPE //dynSettings.Bench.Dispatcher.Invoke(new Action( // () => // dynSettings.Controller.DynamoViewModel.Log(FScheme.print(expr)) // )); } } } catch (CancelEvaluationException ex) { /* Evaluation was cancelled */ OnRunCancelled(false); //this.RunCancelled = false; if (ex.Force) { runAgain = false; } } catch (Exception ex) { /* Evaluation failed due to error */ // NOPE //if (dynSettings.Bench != null) //{ // //Print unhandled exception // if (ex.Message.Length > 0) // { // dynSettings.Bench.Dispatcher.Invoke(new Action( // delegate { dynSettings.Controller.DynamoViewModel.Log(ex); } // )); // } //} OnRunCancelled(true); RunCancelled = true; runAgain = false; } OnEvaluationCompleted(); }
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); } } }