Beispiel #1
0
        public static string ConvertNodesToCode(IEnumerable<NodeModel> nodeList)
        {
            var astBuilder = new AstBuilder(null);
            var astNodes = astBuilder.CompileToAstNodes(nodeList, false);

            string code = GraphToDSCompiler.GraphUtilities.ASTListToCode(astNodes);
            return code;
        }
Beispiel #2
0
        public static string ConvertNodesToCode(DynamoModel dynamoModel, IEnumerable<NodeModel> nodeList)
        {
            var astBuilder = new AstBuilder(dynamoModel, null);
            var astNodes = astBuilder.CompileToAstNodes(nodeList, false);

            var codeGen = new ProtoCore.CodeGenDS(astNodes);
            return codeGen.GenerateCode();
        }
Beispiel #3
0
        /// <summary>
        /// Generate graph sync data based on the input Dynamo nodes. Return
        /// false if all nodes are clean.
        /// </summary>
        /// <param name="nodes"></param>
        /// <returns></returns>
        public bool GenerateGraphSyncData(IEnumerable <NodeModel> nodes)
        {
            var activeNodes = nodes.Where(n => n.State != ElementState.Error);

            if (activeNodes.Any())
            {
                astBuilder.CompileToAstNodes(activeNodes, true);
            }

            return(VerifyGraphSyncData());
        }
Beispiel #4
0
        private List<AssociativeNode> GetAstsForBranch(int branch, List<AssociativeNode> inputAstNodes, bool verboseLogging, AstBuilder builder)
        {
            // Get all upstream nodes and then remove nodes that are not 
            var nodes = GetInScopeNodesForInport(branch, false).Where(n => !(n is Symbol));
            nodes = ScopedNodeModel.GetNodesInTopScope(nodes);

            // The second parameter, isDeltaExecution, is set to false so that
            // all AST nodes will be added to this IF graph node instead of 
            // adding to the corresponding graph node. 
            var allAstNodes = builder.CompileToAstNodes(nodes, Dynamo.DSEngine.AstBuilder.CompilationContext.None, verboseLogging);
            var astNodes = allAstNodes.SelectMany(t => t.Item2).ToList();
            astNodes.Add(AstFactory.BuildReturnStatement(inputAstNodes[branch]));
            return astNodes;
        }
Beispiel #5
0
        private List<AssociativeNode> GetAstsForBranch(int branch, List<AssociativeNode> inputAstNodes)
        {
            AstBuilder astBuilder = new AstBuilder(null);

            // Get all upstream nodes and then remove nodes that are not 
            var nodes = GetInScopeNodesForInport(branch, false).Where(n => !(n is Symbol));
            nodes = ScopedNodeModel.GetNodesInTopScope(nodes);

            // The second parameter, isDeltaExecution, is set to false so that
            // all AST nodes will be added to this IF graph node instead of 
            // adding to the corresponding graph node. 
            var astNodes = astBuilder.CompileToAstNodes(nodes, false);
            astNodes.Add(AstFactory.BuildReturnStatement(inputAstNodes[branch]));
            return astNodes;
        }
Beispiel #6
0
        /// <summary>
        /// Compile a set of nodes to ASTs.
        ///
        /// Note:
        /// 1. Nodes should be a clique with regarding to convertibility and
        ///    selection state. That is, these nodes can be safely to be
        ///    converted into a single code block node. It shouldn't have
        ///    unconvertible or unselected node on any path (if there is) that
        ///    connects any two of these nodes, otherwise there will be
        ///    circular references between unconvertible/unselected node and
        ///    code block node.
        ///
        ///    To split arbitary node set into cliques, use
        ///    NodeToCodeUtils.GetCliques().
        ///
        /// 2. WorkspaceNodes are all nodes in current workspace. We need the
        ///    whole graph so that each to-be-converted node will have correct
        ///    order in the final code block node.
        /// </summary>
        /// <param name="core">Library core</param>
        /// <param name="astBuilder">Ast builder</param>
        /// <param name="workspaceNodes">The whole workspace nodes</param>
        /// <param name="nodes">Selected node that can be converted to a single code block node</param>
        /// <returns></returns>
        public static NodeToCodeResult NodeToCode(
            ProtoCore.Core core,
            AstBuilder astBuilder,
            IEnumerable <NodeModel> workspaceNodes,
            IEnumerable <NodeModel> nodes)
        {
            // The basic worflow is:
            //   1. Compile each node to get its cde in AST format
            //
            //   2. Variable numbering to avoid confliction. For example, two
            //      code block nodes both have assignment "y = x", we need to
            //      rename "y" to "y1" and "y2" respectively.
            //
            //   3. Variable remapping. For example, code block node
            //      "x = 1" connects to "a = b", where the second code block
            //      node will have initialization "b = x_guid" where "x_guid"
            //      is because of variable mappining in the first code block
            //      node. We should restore it to its original name.
            //
            //      Note in step 2 we may rename "x" to "xn".
            //
            //   4. Generate short name for long name variables. Typically they
            //      are from output ports from other nodes.
            //
            //   5. Do constant progation to optimize the generated code.
            #region Step 1 AST compilation

            var sortedGraph = AstBuilder.TopologicalSortForGraph(workspaceNodes);
            var sortedNodes = sortedGraph.Where(nodes.Contains);

            var allAstNodes = astBuilder.CompileToAstNodes(sortedNodes, AstBuilder.CompilationContext.NodeToCode, false);

            #endregion

            #region Step 2 Varialbe numbering

            // External inputs will be in input map
            // Internal non-cbn will be input map & output map
            // Internal cbn will be in renaming map and output map

            // Map from mapped variable to its original name. These variables
            // are from code block nodes that in the selection.
            Dictionary <string, string> renamingMap = null;;

            // Input variable to renamed input variable map
            Dictionary <string, string> inputMap = null;

            // Output variable to renamed output variable map
            Dictionary <string, string> outputMap = null;

            // Collect all inputs/outputs/candidate renaming variables
            GetInputOutputMap(nodes, out inputMap, out outputMap, out renamingMap);

            // Variable numbering map. Value field indicates current current
            // numbering value of the variable. For example, there are variables
            // t1, t2, ... tn and the ID of variable t's NumberingState is n.
            var numberingMap = new Dictionary <string, NumberingState>();

            // In this step, we'll renumber all variables that going to be in
            // the same code block node. That is,
            //
            //     "x = 1; y = x;"   and
            //     "x = 2; y = x;"
            //
            // Will be renumbered to
            //
            //    "x1 = 1; y1 = x1;" and
            //    "x2 = 2; y2 = x2;"
            var mappedVariables = new HashSet <string>();
            foreach (var t in allAstNodes)
            {
                // Reset variable numbering map
                foreach (var p in numberingMap)
                {
                    p.Value.IsNewSession = true;
                }

                foreach (var astNode in t.Item2)
                {
                    VariableNumbering(core, astNode, t.Item1, numberingMap, renamingMap, inputMap, outputMap, mappedVariables);
                }
            }

            renamingMap = renamingMap.Where(p => !p.Key.Contains("%"))
                          .ToDictionary(p => p.Key, p => p.Value);
            #endregion

            #region Step 3 Variable remapping
            foreach (var ts in allAstNodes)
            {
                foreach (var astNode in ts.Item2)
                {
                    VariableRemapping(core, astNode, renamingMap, outputMap, mappedVariables);
                }
            }
            #endregion

            #region Step 4 Generate short name
            var nameGenerator = new ShortNameGenerator();

            // temporary variables are double mapped.
            foreach (var key in outputMap.Keys.ToList())
            {
                if (key.StartsWith(Constants.kTempVarForNonAssignment) &&
                    outputMap[key].StartsWith(Constants.kTempVarForNonAssignment))
                {
                    string shortName = nameGenerator.GetNextName();
                    while (mappedVariables.Contains(shortName))
                    {
                        shortName = nameGenerator.GetNextName();
                    }

                    var tempVar = outputMap[key];
                    outputMap[key]     = shortName;
                    outputMap[tempVar] = shortName;

                    mappedVariables.Add(shortName);
                }
            }

            foreach (var ts in allAstNodes)
            {
                foreach (var astNode in ts.Item2)
                {
                    ShortNameMapping(core, astNode, inputMap, nameGenerator, mappedVariables);
                    foreach (var kvp in inputMap)
                    {
                        if (kvp.Value != String.Empty && outputMap.ContainsKey(kvp.Key))
                        {
                            outputMap[kvp.Key] = kvp.Value;
                        }
                    }
                    ShortNameMapping(core, astNode, outputMap, nameGenerator, mappedVariables);
                }
            }
            #endregion

            var result = new NodeToCodeResult(allAstNodes.SelectMany(x => x.Item2), inputMap, outputMap);
            return(result);
        }