123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using NTERA.Engine;
- using NTERA.Engine.Compiler;
- using NTERA.Engine.Runtime;
- namespace NTERA.Compiler
- {
- public class Compiler
- {
- public string InputDirectory { get; }
- public List<Tuple<ParserError, string>> Errors { get; } = new List<Tuple<ParserError, string>>();
- public List<Tuple<ParserError, string>> Warnings { get; } = new List<Tuple<ParserError, string>>();
- public Dictionary<FunctionDefinition, string> DeclaredProcedures = new Dictionary<FunctionDefinition, string>();
- public int Threads { get; set; }
- public Compiler(string inputDirectory, int threads)
- {
- InputDirectory = inputDirectory;
- Threads = threads;
- }
- public void Compile(string outputDirectory)
- {
- var globals = new VariableDictionary();
- foreach (var variable in BaseDefinitions.DefaultGlobalVariables)
- globals.Add(variable.Name, variable.CalculatedValue);
- string csvPath = Path.Combine(InputDirectory, "CSV");
- string erbPath = Path.Combine(InputDirectory, "ERB");
- var csvDefinition = new CSVDefinition();
- Console.WriteLine("Preprocessing CSV files...");
- foreach (var file in Directory.EnumerateFiles(csvPath, "*.csv", SearchOption.AllDirectories))
- {
- string path = Path.GetFileNameWithoutExtension(file);
- if (path.EndsWith("_TR"))
- continue;
- Preprocessor.ProcessCSV(csvDefinition, path, File.ReadLines(file, Encoding.UTF8));
- }
- Console.WriteLine("Preprocessing header files...");
- ConcurrentBag<FunctionVariable> preprocessedConstants = new ConcurrentBag<FunctionVariable>();
- #if DEBUG
- foreach (var file in Directory.EnumerateFiles(erbPath, "*.erh", SearchOption.AllDirectories))
- #else
- Parallel.ForEach(Directory.EnumerateFiles(erbPath, "*.erh", SearchOption.AllDirectories), new ParallelOptions
- {
- MaxDegreeOfParallelism = Threads
- }, file =>
- #endif
- {
- try
- {
- foreach (var variable in Preprocessor.PreprocessHeaderFile(File.ReadAllText(file)))
- preprocessedConstants.Add(variable);
- }
- catch (Exception ex)
- {
- lock (Errors)
- Errors.Add(new Tuple<ParserError, string>(new ParserError($"Internal pre-process lexer error [{ex}]", new Marker()), Path.GetFileName(file)));
- }
- #if DEBUG
- }
- #else
- });
- #endif
- Console.WriteLine("Preprocessing functions...");
- ConcurrentDictionary<FunctionDefinition, string> preprocessedFunctions = new ConcurrentDictionary<FunctionDefinition, string>();
- #if DEBUG
- foreach (var file in Directory.EnumerateFiles(erbPath, "*.erb", SearchOption.AllDirectories))
- #else
- Parallel.ForEach(Directory.EnumerateFiles(erbPath, "*.erb", SearchOption.AllDirectories), new ParallelOptions
- {
- MaxDegreeOfParallelism = Threads
- }, file =>
- #endif
- {
- try
- {
- foreach (var kv in Preprocessor.PreprocessCodeFile(File.ReadAllText(file), Path.GetFileName(file), preprocessedConstants.ToArray()))
- preprocessedFunctions[kv.Key] = kv.Value;
- }
- catch (Exception ex)
- {
- lock (Errors)
- Errors.Add(new Tuple<ParserError, string>(new ParserError($"Internal pre-process lexer error [{ex}]", new Marker()), Path.GetFileName(file)));
- }
- #if DEBUG
- }
- #else
- });
- #endif
- DeclaredProcedures = preprocessedFunctions.ToDictionary(kv => kv.Key, kv => kv.Value);
- var declaredFunctions = BaseDefinitions.DefaultGlobalFunctions.ToList();
- declaredFunctions.AddRange(DeclaredProcedures.Keys.Where(x => x.IsReturnFunction));
- var procedures = DeclaredProcedures.Keys.Where(x => !x.IsReturnFunction).ToList();
- Console.WriteLine("Compiling functions...");
- #if DEBUG
- foreach (var kv in DeclaredFunctions)
- #else
- Parallel.ForEach(DeclaredProcedures, new ParallelOptions
- {
- MaxDegreeOfParallelism = Threads
- }, kv =>
- #endif
- {
- try
- {
- var locals = new VariableDictionary();
- foreach (var param in kv.Key.Variables)
- locals[param.Name] = param.CalculatedValue;
- Parser parser = new Parser(kv.Value, kv.Key, declaredFunctions, procedures, globals, locals, BaseDefinitions.DefaultKeywords, csvDefinition, preprocessedConstants.ToArray());
- var nodes = parser.Parse(out var localErrors, out var localWarnings);
- lock (Errors)
- Errors.AddRange(localErrors.Select(x => new Tuple<ParserError, string>(x, $"{kv.Key.Filename} - {kv.Key.Name}")));
- lock (Warnings)
- Warnings.AddRange(localWarnings.Select(x => new Tuple<ParserError, string>(x, $"{kv.Key.Filename} - {kv.Key.Name}")));
- }
- catch (Exception ex)
- {
- lock (Errors)
- Errors.Add(new Tuple<ParserError, string>(new ParserError($"Internal post-process lexer error [{ex}]", new Marker()), $"{kv.Key.Filename} - {kv.Key.Name}"));
- }
- #if DEBUG
- }
- #else
- });
- #endif
- long fileSize = 0;
- int fileCount = 0;
- foreach (var file in Directory.EnumerateFiles(InputDirectory, "*.erb", SearchOption.AllDirectories))
- {
- var info = new FileInfo(file);
- fileSize += info.Length;
- fileCount++;
- }
- var htmlWriter = new HTMLWriter
- {
- Errors = Errors.OrderBy(x => x.Item2).ToList(),
- Warnings = Warnings.OrderBy(x => x.Item2).ToList(),
- FunctionCount = DeclaredProcedures.Count,
- TotalFileSize = fileSize,
- TotalFileCount = fileCount
- };
- using (var stream = File.Create(Path.Combine(outputDirectory, "report.html")))
- htmlWriter.WriteReportToFile(stream);
- }
- }
- }
|