public static Dictionary <string, BooScriptAssembly> SerialCompile(IEnumerable <BooScriptAssemblyConfig> scriptConfigs, IEnumerable <Assembly> references, IEnumerable <string> imports = null, IEnumerable <EnsuredMethodSignature> ensuredMethodSignatures = null) { var assemblies = new Dictionary <string, BooScriptAssembly>(); var configs = new Dictionary <string, BooScriptAssemblyConfig>(); var bc = new BlockingCollection <CompilerContext>(); foreach (var cfg in scriptConfigs) { if (!configs.ContainsKey(cfg.AssemblyName)) { configs.Add(cfg.AssemblyName, cfg); } else { //duplicate found Console.WriteLine($"Skipping build of duplicate Assembly, '{cfg.AssemblyName}'"); } } //compiles scripts into assemblies, using n tasks/threads. foreach (var kvp in configs) { var cfg = kvp.Value; var buildTime = DateTime.Now; var context = Compile(cfg.AssemblyName, cfg.FileNames, references, imports, ensuredMethodSignatures); var scriptAssembly = new BooScriptAssembly(buildTime, context); assemblies.Add(cfg.AssemblyName, scriptAssembly); if (context.Errors.Count > 0) { foreach (var err in context.Errors) { Console.WriteLine($"Error: {err.LexicalInfo.FullPath} {err.LexicalInfo.Line},{err.LexicalInfo.Column} {err.Message}"); } } else if (context.Warnings.Count > 0) { foreach (var war in context.Warnings) { Console.WriteLine($"Warning: {war.LexicalInfo.FullPath} {war.LexicalInfo.Line},{war.LexicalInfo.Column} {war.Message}"); } } } return(assemblies); }
public static Dictionary <string, BooScriptAssembly> ParallelCompile(IEnumerable <BooScriptAssemblyConfig> scriptConfigs, IEnumerable <Assembly> references, IEnumerable <string> imports = null, IEnumerable <EnsuredMethodSignature> ensuredMethodSignatures = null) { var assemblies = new ConcurrentDictionary <string, BooScriptAssembly>(); var configs = new Dictionary <string, BooScriptAssemblyConfig>(); var bc = new BlockingCollection <CompilerContext>(); foreach (var cfg in scriptConfigs) { if (!configs.ContainsKey(cfg.AssemblyName)) { configs.Add(cfg.AssemblyName, cfg); } else { //duplicate found Console.WriteLine($"Skipping build of duplicate Assembly, '{cfg.AssemblyName}'"); } } //compiles scripts into assemblies, using n tasks/threads. var compileTask = Task.Factory.StartNew(() => { var result = Parallel.ForEach(configs.Values, cfg => { var buildTime = DateTime.Now; var context = Compile(cfg.AssemblyName, cfg.FileNames, references, imports, ensuredMethodSignatures); var scriptAssembly = new BooScriptAssembly(buildTime, context); assemblies.TryAdd(cfg.AssemblyName, scriptAssembly); bc.Add(context); }); bc.CompleteAdding(); }); //consumes contexts, and writes out errors or warnings.. var reportTask = Task.Factory.StartNew(() => { try { Debug.WriteLine($"Starting reporting..."); while (true) { var context = bc.Take(); if (context.Errors.Count > 0) { foreach (var err in context.Errors) { Console.WriteLine($"Error: {err.LexicalInfo.FullPath} {err.LexicalInfo.Line},{err.LexicalInfo.Column} {err.Message}"); } } else if (context.Warnings.Count > 0) { foreach (var war in context.Warnings) { Console.WriteLine($"Warning: {war.LexicalInfo.FullPath} {war.LexicalInfo.Line},{war.LexicalInfo.Column} {war.Message}"); } } } } catch (InvalidOperationException ioex) { //end Debug.WriteLine($"BlockingCollection threw InvalidOperationException. ( Probably completed. )"); } catch (Exception ex) { Debug.WriteLine($"BlockingCollection threw exception; {ex.Message}"); } }); Task.WaitAll(reportTask, compileTask); //Task.WaitAll(compileTask); return(new Dictionary <string, BooScriptAssembly>(assemblies)); }
//HACK - work around an api design wart. BooScriptAssembly.Build() expecs a Func with a BooScriptAssembly instance, but we also want a standalone instance method for our own use... internal static CompilerContext Compile(BooScriptAssembly scriptAssembly) { return(((Script)scriptAssembly).Compile()); }