示例#1
0
        /// <summary>
        ///     Get a dynFunction from a guid, also stores type internally info for future instantiation.
        ///     And add the compiled node to the enviro
        ///     As a side effect, any of its dependent nodes are also initialized.
        /// </summary>
        /// <param name="environment">The environment from which to get the </param>
        /// <param name="guid">Open a definition from a path, without instantiating the nodes or dependents</param>
        public bool GetNodeInstance(Guid guid, out Function result)
        {
            var controller = dynSettings.Controller;

            if (!this.Contains(guid))
            {
                result = null;
                return(false);
            }

            FunctionDefinition def = null;

            if (!this.IsInitialized(guid))
            {
                if (!GetDefinitionFromPath(guid, out def))
                {
                    result = null;
                    return(false);
                }
            }
            else
            {
                def = this.LoadedCustomNodes[guid];
            }

            WorkspaceModel ws = def.WorkspaceModel;

            IEnumerable <string> inputs =
                ws.Nodes.Where(e => e is Symbol)
                .Select(s => (s as Symbol).InputSymbol);

            IEnumerable <string> outputs =
                ws.Nodes.Where(e => e is Output)
                .Select(o => (o as Output).Symbol);

            if (!outputs.Any())
            {
                var topMost = new List <Tuple <int, NodeModel> >();

                IEnumerable <NodeModel> topMostNodes = ws.GetTopMostNodes();

                foreach (NodeModel topNode in topMostNodes)
                {
                    foreach (int output in Enumerable.Range(0, topNode.OutPortData.Count))
                    {
                        if (!topNode.HasOutput(output))
                        {
                            topMost.Add(Tuple.Create(output, topNode));
                        }
                    }
                }

                outputs = topMost.Select(x => x.Item2.OutPortData[x.Item1].NickName);
            }

            result          = controller.DynamoViewModel.CreateFunction(inputs, outputs, def);
            result.NickName = ws.Name;

            return(true);
        }
示例#2
0
        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);
        }
示例#3
0
        /// <summary>
        /// Compiles this custom node definition, updating all UI instances to match
        /// inputs and outputs and registering new definition with the EngineController.
        /// </summary>
        public void Compile(DynamoModel dynamoModel, EngineController controller)
        {
            // If we are loading dyf file, dont compile it until all nodes are loaded
            // otherwise some intermediate function defintions will be created.
            // TODO: This is a hack, in reality we should be preventing this from being called at the Workspace.RequestSync() level --SJE
            if (IsBeingLoaded || IsProxy)
            {
                return;
            }

            #region Outputs and Inputs and UI updating

            #region Find outputs

            // Find output elements for the node
            List <Output> outputs = WorkspaceModel.Nodes.OfType <Output>().ToList();

            var topMost = new List <Tuple <int, NodeModel> >();

            List <string> outNames;

            // 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 => Tuple.Create(0, x as NodeModel)));
                outNames = outputs.Select(x => x.Symbol).ToList();
            }
            else
            {
                outNames = new List <string>();

                // if there are no explicitly defined output nodes
                // get the top most nodes and set THEM as the output
                IEnumerable <NodeModel> topMostNodes = WorkspaceModel.GetTopMostNodes();

                var rtnPorts =
                    //Grab multiple returns from each node
                    topMostNodes.SelectMany(
                        topNode =>
                        //If the node is a recursive instance...
                        topNode is Function && (topNode as Function).Definition == this
                        // infinity output
                                ? new[] { new { portIndex = 0, node = topNode, name = "∞" } }
                        // otherwise, grab all ports with connected outputs and package necessary info
                                : topNode.OutPortData
                        .Select(
                            (port, i) =>
                            new { portIndex = i, node = topNode, name = port.NickName })
                        .Where(x => !topNode.HasOutput(x.portIndex)));

                foreach (var rtnAndIndex in rtnPorts.Select((rtn, i) => new { rtn, idx = i }))
                {
                    topMost.Add(Tuple.Create(rtnAndIndex.rtn.portIndex, rtnAndIndex.rtn.node));
                    outNames.Add(rtnAndIndex.rtn.name ?? rtnAndIndex.idx.ToString());
                }
            }

            var nameDict = new Dictionary <string, int>();
            foreach (var name in outNames)
            {
                if (nameDict.ContainsKey(name))
                {
                    nameDict[name]++;
                }
                else
                {
                    nameDict[name] = 0;
                }
            }

            nameDict = nameDict.Where(x => x.Value != 0).ToDictionary(x => x.Key, x => x.Value);

            outNames.Reverse();

            var keys = new List <string>();
            foreach (var name in outNames)
            {
                int amt;
                if (nameDict.TryGetValue(name, out amt))
                {
                    nameDict[name] = amt - 1;
                    keys.Add(name == "" ? amt + ">" : name + amt);
                }
                else
                {
                    keys.Add(name);
                }
            }

            keys.Reverse();

            ReturnKeys = keys;

            #endregion

            //Find function entry point, and then compile
            var inputNodes = WorkspaceModel.Nodes.OfType <Symbol>().ToList();
            var parameters = inputNodes.Select(x => string.IsNullOrEmpty(x.InputSymbol) ? x.AstIdentifierForPreview.Value: x.InputSymbol);
            Parameters = inputNodes.Select(x => x.InputSymbol);

            //Update existing function nodes which point to this function to match its changes
            var customNodeInstances = dynamoModel.AllNodes
                                      .OfType <Function>()
                                      .Where(el => el.Definition != null && el.Definition == this);

            foreach (var node in customNodeInstances)
            {
                node.ResyncWithDefinition();
            }

            //Call OnSave for all saved elements
            foreach (var node in WorkspaceModel.Nodes)
            {
                node.OnSave();
            }

            #endregion

            var outputNodes = topMost.Select((x) =>
            {
                var n = x.Item2.GetAstIdentifierForOutputIndex(x.Item1);
                return(n as AssociativeNode);
            });

#if ENABLE_DYNAMO_SCHEDULER
            var initParams = new CompileCustomNodeParams()
            {
                EngineController = controller,
                Definition       = this,
                Nodes            = WorkspaceModel.Nodes.Where(x => !(x is Symbol)),
                Parameters       = parameters,
                Outputs          = outputNodes
            };

            // Schedule the compilation of CustomNodeDefinition, we are
            // not interested in when it will be completed, so no callback.
            var scheduler = dynamoModel.Scheduler;
            var task      = new CompileCustomNodeAsyncTask(scheduler);
            if (task.Initialize(initParams))
            {
                scheduler.ScheduleForExecution(task);
            }
#else
            controller.GenerateGraphSyncDataForCustomNode(
                this,
                WorkspaceModel.Nodes.Where(x => !(x is Symbol)),
                outputNodes,
                parameters);
#endif

            // Not update graph until Run
            // if (success)
            //    controller.UpdateGraph();
        }