Exemplo n.º 1
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 => x.GetAstIdentifierForOutputIndex(0).Value);
            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;
            });

            controller.GenerateGraphSyncDataForCustomNode(
                this,
                WorkspaceModel.Nodes.Where(x => !(x is Symbol)),
                outputNodes,
                parameters);

            // Not update graph until Run 
            // if (success)
            //    controller.UpdateGraph();
        }
Exemplo n.º 2
0
        private static Value ConvertAllResults(List<object> results)
        {
            //if there are multiple items in the results list
            //return a list type
            if (results.Count > 1)
            {
                FSharpList<Value> lst = FSharpList<Value>.Empty;

                //reverse the results list so our CONs list isn't backwards
                results.Reverse();

                lst = results.Aggregate(lst,
                                        (current, result) =>
                                        FSharpList<Value>.Cons(DynamoTypeConverter.ConvertToValue(result), current));

                //the result will be a list of objects if any lists
                return Value.NewList(lst);
            }
            //otherwise, return a single value
            else
            {
                return DynamoTypeConverter.ConvertToValue(results.First());
            }
        }
Exemplo n.º 3
0
        public CustomNodeDefinition(
            Guid functionId,
            string displayName="",
            IList<NodeModel> nodeModels=null)
        {
            if (functionId == Guid.Empty)
                throw new ArgumentException(@"FunctionId invalid.", "functionId");

            nodeModels = nodeModels ?? new List<NodeModel>();

            #region Find outputs

            // Find output elements for the node

            var outputs = nodeModels.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 = nodeModels.Where(node => node.IsTopMostNode);

                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.FunctionId == functionId
                                // 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 returnKeys = new List<string>();
            foreach (var name in outNames)
            {
                int amt;
                if (nameDict.TryGetValue(name, out amt))
                {
                    nameDict[name] = amt - 1;
                    returnKeys.Add(name == "" ? amt + ">" : name + amt);
                }
                else
                    returnKeys.Add(name);
            }

            returnKeys.Reverse();

            #endregion

            #region Find inputs

            //Find function entry point, and then compile
            var inputNodes = nodeModels.OfType<Symbol>().ToList();
            var parameters = inputNodes.Select(x => new TypedParameter(
                                                   x.GetAstIdentifierForOutputIndex(0).Value, 
                                                   x.Parameter.Type, 
                                                   x.Parameter.DefaultValue));
            var displayParameters = inputNodes.Select(x => x.Parameter.Name);

            #endregion

            FunctionBody = nodeModels.Where(node => !(node is Symbol));
            DisplayName = displayName;
            FunctionId = functionId;
            Parameters = parameters;
            ReturnKeys = returnKeys;
            DisplayParameters = displayParameters;
            OutputNodes = topMost.Select(x => x.Item2.GetAstIdentifierForOutputIndex(x.Item1));
            DirectDependencies = nodeModels
                .OfType<Function>()
                .Select(node => node.Definition)
                .Where(def => def.FunctionId != functionId)
                .Distinct();
        }