Compiler.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using NTERA.Engine;
  9. using NTERA.Engine.Compiler;
  10. using NTERA.Engine.Runtime;
  11. namespace NTERA.Compiler
  12. {
  13. public class Compiler
  14. {
  15. public string InputDirectory { get; }
  16. public List<Tuple<ParserError, string>> Errors { get; } = new List<Tuple<ParserError, string>>();
  17. public List<Tuple<ParserError, string>> Warnings { get; } = new List<Tuple<ParserError, string>>();
  18. public Dictionary<FunctionDefinition, string> DeclaredProcedures = new Dictionary<FunctionDefinition, string>();
  19. public int Threads { get; set; }
  20. public Compiler(string inputDirectory, int threads)
  21. {
  22. InputDirectory = inputDirectory;
  23. Threads = threads;
  24. }
  25. public void Compile(string outputDirectory)
  26. {
  27. string csvPath = Path.Combine(InputDirectory, "CSV");
  28. string erbPath = Path.Combine(InputDirectory, "ERB");
  29. var csvDefinition = new CSVDefinition();
  30. Console.WriteLine("Preprocessing CSV files...");
  31. foreach (var file in Directory.EnumerateFiles(csvPath, "*.csv", SearchOption.AllDirectories))
  32. {
  33. string path = Path.GetFileNameWithoutExtension(file);
  34. if (path.EndsWith("_TR"))
  35. continue;
  36. Preprocessor.ProcessCSV(csvDefinition, path, File.ReadLines(file, Encoding.UTF8));
  37. }
  38. Console.WriteLine("Preprocessing header files...");
  39. ConcurrentBag<FunctionVariable> preprocessedConstants = new ConcurrentBag<FunctionVariable>();
  40. #if DEBUG
  41. foreach (var file in Directory.EnumerateFiles(erbPath, "*.erh", SearchOption.AllDirectories))
  42. #else
  43. Parallel.ForEach(Directory.EnumerateFiles(erbPath, "*.erh", SearchOption.AllDirectories), new ParallelOptions
  44. {
  45. MaxDegreeOfParallelism = Threads
  46. }, file =>
  47. #endif
  48. {
  49. try
  50. {
  51. foreach (var variable in Preprocessor.PreprocessHeaderFile(File.ReadAllText(file)))
  52. preprocessedConstants.Add(variable);
  53. }
  54. catch (Exception ex)
  55. {
  56. lock (Errors)
  57. Errors.Add(new Tuple<ParserError, string>(new ParserError($"Internal pre-process lexer error [{ex}]", new Marker()), Path.GetFileName(file)));
  58. }
  59. #if DEBUG
  60. }
  61. #else
  62. });
  63. #endif
  64. Console.WriteLine("Preprocessing functions...");
  65. ConcurrentDictionary<FunctionDefinition, string> preprocessedFunctions = new ConcurrentDictionary<FunctionDefinition, string>();
  66. #if DEBUG
  67. foreach (var file in Directory.EnumerateFiles(erbPath, "*.erb", SearchOption.AllDirectories))
  68. #else
  69. Parallel.ForEach(Directory.EnumerateFiles(erbPath, "*.erb", SearchOption.AllDirectories), new ParallelOptions
  70. {
  71. MaxDegreeOfParallelism = Threads
  72. }, file =>
  73. #endif
  74. {
  75. try
  76. {
  77. foreach (var kv in Preprocessor.PreprocessCodeFile(File.ReadAllText(file), Path.GetFileName(file), preprocessedConstants.ToArray()))
  78. preprocessedFunctions[kv.Key] = kv.Value;
  79. }
  80. catch (Exception ex)
  81. {
  82. lock (Errors)
  83. Errors.Add(new Tuple<ParserError, string>(new ParserError($"Internal pre-process lexer error [{ex}]", new Marker()), Path.GetFileName(file)));
  84. }
  85. #if DEBUG
  86. }
  87. #else
  88. });
  89. #endif
  90. DeclaredProcedures = preprocessedFunctions.ToDictionary(kv => kv.Key, kv => kv.Value);
  91. var declaredFunctions = BaseDefinitions.DefaultGlobalFunctions.ToList();
  92. declaredFunctions.AddRange(DeclaredProcedures.Keys.Where(x => x.IsReturnFunction));
  93. var procedures = DeclaredProcedures.Keys.Where(x => !x.IsReturnFunction).ToList();
  94. Console.WriteLine("Compiling functions...");
  95. #if DEBUG
  96. foreach (var kv in DeclaredProcedures)
  97. #else
  98. Parallel.ForEach(DeclaredProcedures, new ParallelOptions
  99. {
  100. MaxDegreeOfParallelism = Threads
  101. }, kv =>
  102. #endif
  103. {
  104. try
  105. {
  106. Parser parser = new Parser(kv.Value, kv.Key, declaredFunctions, procedures, BaseDefinitions.DefaultGlobalVariables, kv.Key.Variables, BaseDefinitions.DefaultKeywords, csvDefinition, preprocessedConstants.ToArray());
  107. var nodes = parser.Parse(out var localErrors, out var localWarnings);
  108. lock (Errors)
  109. Errors.AddRange(localErrors.Select(x => new Tuple<ParserError, string>(x, $"{kv.Key.Filename} - {kv.Key.Name}")));
  110. lock (Warnings)
  111. Warnings.AddRange(localWarnings.Select(x => new Tuple<ParserError, string>(x, $"{kv.Key.Filename} - {kv.Key.Name}")));
  112. }
  113. catch (Exception ex)
  114. {
  115. lock (Errors)
  116. Errors.Add(new Tuple<ParserError, string>(new ParserError($"Internal post-process lexer error [{ex}]", new Marker()), $"{kv.Key.Filename} - {kv.Key.Name}"));
  117. }
  118. #if DEBUG
  119. }
  120. #else
  121. });
  122. #endif
  123. long fileSize = 0;
  124. int fileCount = 0;
  125. foreach (var file in Directory.EnumerateFiles(InputDirectory, "*.erb", SearchOption.AllDirectories))
  126. {
  127. var info = new FileInfo(file);
  128. fileSize += info.Length;
  129. fileCount++;
  130. }
  131. var htmlWriter = new HTMLWriter
  132. {
  133. Errors = Errors.OrderBy(x => x.Item2).ToList(),
  134. Warnings = Warnings.OrderBy(x => x.Item2).ToList(),
  135. FunctionCount = DeclaredProcedures.Count,
  136. TotalFileSize = fileSize,
  137. TotalFileCount = fileCount
  138. };
  139. using (var stream = File.Create(Path.Combine(outputDirectory, "report.html")))
  140. htmlWriter.WriteReportToFile(stream);
  141. }
  142. }
  143. }