internal override IEnumerable<AssociativeNode> BuildAst(List<AssociativeNode> inputAstNodes, AstBuilder.CompilationContext context) { var rhs = AstFactory.BuildStringNode(Value); var assignment = AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), rhs); return new[] { assignment }; }
public EngineController(DynamoModel dynamoModel, string geometryFactoryFileName) { this.dynamoModel = dynamoModel; // Create a core which is used for parsing code and loading libraries libraryCore = new ProtoCore.Core(new Options() { RootCustomPropertyFilterPathName = string.Empty }); libraryCore.Executives.Add(Language.kAssociative,new ProtoAssociative.Executive(libraryCore)); libraryCore.Executives.Add(Language.kImperative, new ProtoImperative.Executive(libraryCore)); libraryCore.ParsingMode = ParseMode.AllowNonAssignment; libraryServices = new LibraryServices(libraryCore); libraryServices.LibraryLoading += this.LibraryLoading; libraryServices.LibraryLoadFailed += this.LibraryLoadFailed; libraryServices.LibraryLoaded += this.LibraryLoaded; liveRunnerServices = new LiveRunnerServices(dynamoModel, this, geometryFactoryFileName); liveRunnerServices.ReloadAllLibraries(libraryServices.ImportedLibraries); codeCompletionServices = new CodeCompletionServices(LiveRunnerCore); astBuilder = new AstBuilder(dynamoModel, this); syncDataManager = new SyncDataManager(); dynamoModel.NodeDeleted += NodeDeleted; }
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(); }
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; }
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; }
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; }
public EngineController(DynamoController controller) { libraryServices = LibraryServices.GetInstance(); libraryServices.LibraryLoading += this.LibraryLoading; libraryServices.LibraryLoadFailed += this.LibraryLoadFailed; libraryServices.LibraryLoaded += this.LibraryLoaded; liveRunnerServices = new LiveRunnerServices(this); liveRunnerServices.ReloadAllLibraries(libraryServices.Libraries.ToList()); astBuilder = new AstBuilder(this); syncDataManager = new SyncDataManager(); this.controller = controller; this.controller.DynamoModel.NodeDeleted += NodeDeleted; }
public EngineController(DynamoModel dynamoModel, string geometryFactoryFileName) { this.dynamoModel = dynamoModel; libraryServices = LibraryServices.GetInstance(); libraryServices.LibraryLoading += this.LibraryLoading; libraryServices.LibraryLoadFailed += this.LibraryLoadFailed; libraryServices.LibraryLoaded += this.LibraryLoaded; liveRunnerServices = new LiveRunnerServices(dynamoModel, this, geometryFactoryFileName); liveRunnerServices.ReloadAllLibraries(libraryServices.Libraries.ToList()); astBuilder = new AstBuilder(dynamoModel, this); syncDataManager = new SyncDataManager(); dynamoModel.NodeDeleted += NodeDeleted; }
public EngineController(DynamoController controller) { libraryServices = LibraryServices.GetInstance(); libraryServices.LibraryLoading += this.LibraryLoading; libraryServices.LibraryLoadFailed += this.LibraryLoadFailed; libraryServices.LibraryLoaded += this.LibraryLoaded; liveRunnerServices = new LiveRunnerServices(this); liveRunnerServices.ReloadAllLibraries(libraryServices.Libraries.ToList()); astBuilder = new AstBuilder(this); syncDataManager = new SyncDataManager(); this.controller = controller; this.controller.DynamoModel.NodeDeleted += NodeDeleted; this.controller.CustomNodeManager.RecompileAllNodes(this); }
public EngineController(LibraryServices libraryServices, string geometryFactoryFileName, bool verboseLogging) { this.libraryServices = libraryServices; libraryServices.LibraryLoaded += LibraryLoaded; CompilationServices = new CompilationServices(libraryServices.LibraryManagementCore); liveRunnerServices = new LiveRunnerServices(this, geometryFactoryFileName); liveRunnerServices.ReloadAllLibraries(libraryServices.ImportedLibraries); libraryServices.SetLiveCore(LiveRunnerCore); codeCompletionServices = new CodeCompletionServices(LiveRunnerCore); astBuilder = new AstBuilder(this); syncDataManager = new SyncDataManager(); VerboseLogging = verboseLogging; }
/// <summary> /// Handler for the EngineController's AstBuilt event. /// Formats a string of AST for preview on the node. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void EngineController_AstBuilt(object sender, AstBuilder.ASTBuiltEventArgs e) { if (e.Node == nodeLogic) { var sb = new StringBuilder(); sb.AppendLine(string.Format("{0} AST:", e.Node.GUID)); foreach (var assocNode in e.AstNodes) { var pretty = assocNode.ToString(); //shorten the guids var strRegex = @"([0-9a-f-]{32}).*?"; var myRegex = new Regex(strRegex, RegexOptions.None); string strTargetString = assocNode.ToString(); foreach (Match myMatch in myRegex.Matches(strTargetString)) { if (myMatch.Success) { pretty = pretty.Replace(myMatch.Value, "..." + myMatch.Value.Substring(myMatch.Value.Length - 7)); } } sb.AppendLine(pretty); } ASTText = sb.ToString(); } }
public AssociativeNode CompileToAstNode(AstBuilder builder) { if (!RequiresRecalc) { return this.AstIdentifier; } builder.ClearAstNodes(GUID); bool isPartiallyApplied = false; // Recursively compile its inputs to ast nodes and add intermediate // nodes to builder var inputAstNodes = new List<AssociativeNode>(); for (int index = 0; index < InPortData.Count; ++index) { Tuple<int, NodeModel> input; if (!TryGetInput(index, out input)) { isPartiallyApplied = true; inputAstNodes.Add(null); } else { inputAstNodes.Add(input.Item2.CompileToAstNode(builder)); } } // Build evaluatiion for this node. If the rhs is a partially // applied function, then a function defintion node will be created. // But in the end there is always an assignment: // // AstIdentifier = ...; var rhs = BuildAstNode(builder, inputAstNodes) ?? builder.BuildEvaluator(this, inputAstNodes); builder.BuildEvaluation(this, rhs, isPartiallyApplied); return AstIdentifier; }
/// <summary> /// Similar to NodeModel.BuildAst(). When compiled to AST, for /// ScopedNodeModel this method will be called when all requirements /// are satisfied. /// </summary> /// <param name="inputAstNodes"></param> /// <param name="verboseLogging"></param> /// <param name="builder"></param> /// <returns></returns> internal virtual IEnumerable<AssociativeNode> BuildAstInScope(List<AssociativeNode> inputAstNodes, bool verboseLogging, AstBuilder builder) { OnBuilt(); var result = BuildOutputAstInScope(inputAstNodes, verboseLogging, builder); return result; }
/// <summary> /// Similar to NodeModel.BuildOutputAst(). When compiled to AST, for /// ScopedNodeModel this method will be called when all requirements are /// satisfied. The derived class needs to implement this method to /// compile its children into some scopes. /// </summary> /// <param name="inputAstNodes"></param> /// <param name="verboseLogging"></param> /// <param name="builder"></param> /// <returns></returns> public virtual IEnumerable<AssociativeNode> BuildOutputAstInScope(List<AssociativeNode> inputAstNodes, bool verboseLogging, AstBuilder builder) { throw new NotImplementedException("BuildOutputAstInScope"); }
internal override IEnumerable<AssociativeNode> BuildAst(List<AssociativeNode> inputAstNodes, AstBuilder.CompilationContext context) { var paramDict = InPortData.Select(x => x.NickName) .Zip<string, AssociativeNode, Tuple<string, AssociativeNode>>(inputAstNodes, Tuple.Create) .ToDictionary(x => x.Item1, x => x.Item2); AssociativeNode rhs; if (null == _parsed) { rhs = AstFactory.BuildNullNode(); } else { List<AssociativeNode> newInputs = _parsed.Count == 1 ? new List<AssociativeNode> { _parsed[0].GetAstNode(paramDict) } : _parsed.Select(x => x.GetAstNode(paramDict)).ToList(); rhs = newInputs.Count == 1 ? newInputs[0] : AstFactory.BuildExprList(newInputs); } var assignment = AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), rhs); return new[] { assignment }; }
/// <summary> /// Wraps the publically overrideable `BuildOutputAst` method so that it works with Preview. /// </summary> /// <param name="inputAstNodes"></param> /// <param name="context">Compilation context</param> internal virtual IEnumerable<AssociativeNode> BuildAst(List<AssociativeNode> inputAstNodes, AstBuilder.CompilationContext context) { OnBuilt(); IEnumerable<AssociativeNode> result = null; try { result = BuildOutputAst(inputAstNodes); } catch (Exception e) { // If any exception from BuildOutputAst(), we emit // a function call "var_guid = %nodeAstFailed(full.node.name)" // for this node, set the state of node to AstBuildBroken and // disply the corresponding error message. // // The return value of function %nodeAstFailed() is always // null. var errorMsg = Properties.Resources.NodeProblemEncountered; var fullMsg = errorMsg + "\n\n" + e.Message; this.NotifyAstBuildBroken(fullMsg); var fullName = this.GetType().ToString(); var astNodeFullName = AstFactory.BuildStringNode(fullName); var arguments = new List<AssociativeNode> { astNodeFullName }; var func = AstFactory.BuildFunctionCall(Constants.kNodeAstFailed, arguments); return new [] { AstFactory.BuildAssignment(AstIdentifierForPreview, func) }; } if (OutPortData.Count == 1) { var firstOuputIdent = GetAstIdentifierForOutputIndex(0); if (!AstIdentifierForPreview.Equals(firstOuputIdent)) { result = result.Concat( new[] { AstFactory.BuildAssignment(AstIdentifierForPreview, firstOuputIdent) }); } return result; } var emptyList = AstFactory.BuildExprList(new List<AssociativeNode>()); var previewIdInit = AstFactory.BuildAssignment(AstIdentifierForPreview, emptyList); return result.Concat(new[] { previewIdInit }) .Concat( OutPortData.Select( (outNode, index) => AstFactory.BuildAssignment( new IdentifierNode(AstIdentifierForPreview) { ArrayDimensions = new ArrayNode { Expr = new StringNode { value = outNode.NickName } } }, GetAstIdentifierForOutputIndex(index)))); }
internal override IEnumerable<AssociativeNode> BuildAst(List<AssociativeNode> inputAstNodes, AstBuilder.CompilationContext context) { //Do not build if the node is in error. if (State == ElementState.Error) { return Enumerable.Empty<AssociativeNode>(); } var resultNodes = new List<AssociativeNode>(); // Define unbound variables if necessary if (inputIdentifiers != null && inputAstNodes != null && inputIdentifiers.Count == inputAstNodes.Count) { var initStatments = inputIdentifiers.Zip(inputAstNodes, (ident, rhs) => { var identNode = AstFactory.BuildIdentifier(ident); if (context != AstBuilder.CompilationContext.NodeToCode) MapIdentifiers(identNode); return AstFactory.BuildAssignment(identNode, rhs); }); resultNodes.AddRange(initStatments); } foreach (var astNode in codeStatements.Select(stmnt => NodeUtils.Clone(stmnt.AstNode))) { if (context != AstBuilder.CompilationContext.NodeToCode) MapIdentifiers(astNode); resultNodes.Add(astNode as AssociativeNode); } return resultNodes; }
public override IEnumerable<AssociativeNode> BuildOutputAstInScope(List<AssociativeNode> inputAstNodes, bool verboseLogging, AstBuilder builder) { // This function will compile IF node to the following format: // // cond = ...; // v = [Imperative] // { // if (cond) { // return = [Associative] { // ... // } // } // else { // return = [Associative] { // ... // } // } // } // var astsInTrueBranch = GetAstsForBranch(1, inputAstNodes, verboseLogging, builder); var astsInFalseBranch = GetAstsForBranch(2, inputAstNodes, verboseLogging, builder); // if (cond) { // return = [Associative] {...} // } var ifBlock = new LanguageBlockNode { codeblock = new LanguageCodeBlock(Language.kAssociative), CodeBlockNode = new CodeBlockNode { Body = astsInTrueBranch } }; var ifBranch = AstFactory.BuildReturnStatement(ifBlock).ToImperativeAST(); // else { // return = [Associative] { ... } // } var elseBlock = new LanguageBlockNode { codeblock = new LanguageCodeBlock(Language.kAssociative), CodeBlockNode = new CodeBlockNode { Body = astsInFalseBranch } }; var elseBranch = AstFactory.BuildReturnStatement(elseBlock).ToImperativeAST(); var ifelseStatement = new ProtoCore.AST.ImperativeAST.IfStmtNode() { IfExprNode = inputAstNodes[0].ToImperativeAST(), IfBody = new List<ProtoCore.AST.ImperativeAST.ImperativeNode> { ifBranch }, ElseBody = new List<ProtoCore.AST.ImperativeAST.ImperativeNode> { elseBranch } }; // thisVariable = [Imperative] // { // ... // } var outerBlock = new LanguageBlockNode { codeblock = new LanguageCodeBlock(Language.kImperative), CodeBlockNode = new ProtoCore.AST.ImperativeAST.CodeBlockNode { Body = new List<ProtoCore.AST.ImperativeAST.ImperativeNode> { ifelseStatement } } }; var thisVariable = GetAstIdentifierForOutputIndex(0); var assignment = AstFactory.BuildAssignment(thisVariable, outerBlock); return new AssociativeNode[] { assignment }; }
/// <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); }