protected void DrakonWorkflowCodeGenerator(BaseController canvasController, GraphicElement elClass, string className, string filename) { IFlowSharpCodeService codeService = ServiceManager.Get <IFlowSharpCodeService>(); GraphicElement el = codeService.FindStartOfWorkflow(canvasController, elClass); if (el == null) { var outputWindow = ServiceManager.Get <IFlowSharpCodeOutputWindowService>(); outputWindow.Clear(); outputWindow.WriteLine("Cannot find shape that is the start of the workflow."); } else { DrakonCodeTree dcg = new DrakonCodeTree(); codeService.ParseDrakonWorkflow(dcg, codeService, canvasController, el); var codeGenSvc = new PythonCodeGeneratorService(); dcg.GenerateCode(codeGenSvc); codeGenSvc.CodeResult.Insert(0, PYLINT + "\n"); File.WriteAllText(filename, codeGenSvc.CodeResult.ToString()); elClass.Json["python"] = codeGenSvc.CodeResult.ToString(); } }
public void Compile() { TerminateRunningProcess(); var outputWindow = ServiceManager.Get <IFlowSharpCodeOutputWindowService>(); outputWindow.Clear(); IFlowSharpCanvasService canvasService = ServiceManager.Get <IFlowSharpCanvasService>(); IFlowSharpMenuService menuService = ServiceManager.Get <IFlowSharpMenuService>(); IFlowSharpCodeService codeService = ServiceManager.Get <IFlowSharpCodeService>(); BaseController canvasController = canvasService.ActiveController; tempToTextBoxMap.Clear(); List <GraphicElement> compiledAssemblies = new List <GraphicElement>(); bool ok = CompileAssemblies(canvasController, compiledAssemblies); if (!ok) { DeleteTempFiles(); return; } List <string> refs = new List <string>(); List <string> sources = new List <string>(); // Add specific assembly references on the drawing. List <IAssemblyReferenceBox> references = GetReferences(canvasController); refs.AddRange(references.Select(r => r.Filename)); List <GraphicElement> rootSourceShapes = GetSources(canvasController); rootSourceShapes.ForEach(root => GetReferencedAssemblies(root).Where(refassy => refassy is IAssemblyBox).ForEach(refassy => refs.Add(((IAssemblyBox)refassy).Filename))); // Get code for workflow boxes first, as this code will then be included in the rootSourceShape code listing. IEnumerable <GraphicElement> workflowShapes = canvasController.Elements.Where(el => el is IWorkflowBox); workflowShapes.ForEach(wf => { string code = GetWorkflowCode(codeService, canvasController, wf); wf.Json["Code"] = code; }); List <GraphicElement> excludeClassShapes = new List <GraphicElement>(); List <GraphicElement> classes = GetClasses(canvasController); // Get CSharpClass shapes that contain DRAKON shapes. classes.Where(cls => HasDrakonShapes(canvasController, cls)).ForEach(cls => { excludeClassShapes.AddRange(canvasController.Elements.Where(el => cls.DisplayRectangle.Contains(el.DisplayRectangle))); DrakonCodeTree dcg = new DrakonCodeTree(); var workflowStart = codeService.FindStartOfWorkflow(canvasController, cls); codeService.ParseDrakonWorkflow(dcg, codeService, canvasController, workflowStart); var codeGenSvc = new CSharpCodeGeneratorService(); dcg.GenerateCode(codeGenSvc); InsertCodeInRunWorkflowMethod(cls, codeGenSvc.CodeResult); string filename = CreateCodeFile(cls); sources.Add(filename); }); rootSourceShapes.Where(root => !excludeClassShapes.Contains(root)).ForEach(root => { // Get all other shapes that are not part of CSharpClass shapes: // TODO: Better Linq! if (!String.IsNullOrEmpty(GetCode(root))) { string filename = CreateCodeFile(root); sources.Add(filename); } }); exeFilename = String.IsNullOrEmpty(menuService.Filename) ? "temp.exe" : Path.GetFileNameWithoutExtension(menuService.Filename) + ".exe"; Compile(exeFilename, sources, refs, true); DeleteTempFiles(); if (!results.Errors.HasErrors) { outputWindow.WriteLine("No Errors"); } }
// =================================================== // DRAKON workflow public GraphicElement ParseDrakonWorkflow(DrakonCodeTree dcg, IFlowSharpCodeService codeService, BaseController canvasController, GraphicElement el, bool inCondition = false) { while (el != null) { // If we're in a conditional and we encounter a shape with multiple "merge" connections, then we assume (I think rightly so) // that this is the end of the conditional branch, and that code should continue at this point outside of the "if-else" statement. if (inCondition) { var connections = el.Connections.Where(c => c.ElementConnectionPoint.Type == GripType.TopMiddle); if (connections.Count() > 1) { return(el); } } // All these if's. Yuck. if (el is IBeginForLoopBox) { var drakonLoop = new DrakonLoop() { Code = ParseCode(el) }; dcg.AddInstruction(drakonLoop); var nextEl = codeService.NextElementInWorkflow(el); if (nextEl != null) { el = ParseDrakonWorkflow(drakonLoop.LoopInstructions, codeService, canvasController, nextEl); } else { // TODO: error -- there are no further elements after the beginning for loop box! ServiceManager.Get <IFlowSharpCodeOutputWindowService>().WriteLine("Error: Drakon start 'for' loop does not have any statements!"); return(el); } } else if (el is IEndForLoopBox) { return(el); } else if (el is IIfBox) { var drakonIf = new DrakonIf() { Code = ParseCode(el) }; dcg.AddInstruction(drakonIf); var elTrue = codeService.GetTruePathFirstShape((IIfBox)el); var elFalse = codeService.GetFalsePathFirstShape((IIfBox)el); if (elTrue != null) { ParseDrakonWorkflow(drakonIf.TrueInstructions, codeService, canvasController, elTrue, true); } if (elFalse != null) { ParseDrakonWorkflow(drakonIf.FalseInstructions, codeService, canvasController, elFalse, true); } // dcg.AddInstruction(new DrakonEndIf()); } else if (el is IOutputBox) { dcg.AddInstruction(new DrakonOutput() { Code = ParseCode(el) }); } else { dcg.AddInstruction(new DrakonStatement() { Code = ParseCode(el) }); } el = codeService.NextElementInWorkflow(el); } return(null); }