Compiler.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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. var globals = new VariableDictionary();
  28. foreach (var variable in BaseDefinitions.DefaultGlobalVariables)
  29. globals.Add(variable.Name, variable.CalculatedValue);
  30. string csvPath = Path.Combine(InputDirectory, "CSV");
  31. string erbPath = Path.Combine(InputDirectory, "ERB");
  32. var csvDefinition = new CSVDefinition();
  33. Console.WriteLine("Preprocessing CSV files...");
  34. foreach (var file in Directory.EnumerateFiles(csvPath, "*.csv", SearchOption.AllDirectories))
  35. {
  36. string path = Path.GetFileNameWithoutExtension(file);
  37. if (path.EndsWith("_TR"))
  38. continue;
  39. Preprocessor.ProcessCSV(csvDefinition, path, File.ReadLines(file, Encoding.UTF8));
  40. }
  41. Console.WriteLine("Preprocessing header files...");
  42. ConcurrentBag<FunctionVariable> preprocessedConstants = new ConcurrentBag<FunctionVariable>();
  43. #if DEBUG
  44. foreach (var file in Directory.EnumerateFiles(erbPath, "*.erh", SearchOption.AllDirectories))
  45. #else
  46. Parallel.ForEach(Directory.EnumerateFiles(erbPath, "*.erh", SearchOption.AllDirectories), new ParallelOptions
  47. {
  48. MaxDegreeOfParallelism = Threads
  49. }, file =>
  50. #endif
  51. {
  52. try
  53. {
  54. foreach (var variable in Preprocessor.PreprocessHeaderFile(File.ReadAllText(file)))
  55. preprocessedConstants.Add(variable);
  56. }
  57. catch (Exception ex)
  58. {
  59. lock (Errors)
  60. Errors.Add(new Tuple<ParserError, string>(new ParserError($"Internal pre-process lexer error [{ex}]", new Marker()), Path.GetFileName(file)));
  61. }
  62. #if DEBUG
  63. }
  64. #else
  65. });
  66. #endif
  67. Console.WriteLine("Preprocessing functions...");
  68. ConcurrentDictionary<FunctionDefinition, string> preprocessedFunctions = new ConcurrentDictionary<FunctionDefinition, string>();
  69. #if DEBUG
  70. foreach (var file in Directory.EnumerateFiles(erbPath, "*.erb", SearchOption.AllDirectories))
  71. #else
  72. Parallel.ForEach(Directory.EnumerateFiles(erbPath, "*.erb", SearchOption.AllDirectories), new ParallelOptions
  73. {
  74. MaxDegreeOfParallelism = Threads
  75. }, file =>
  76. #endif
  77. {
  78. try
  79. {
  80. foreach (var kv in Preprocessor.PreprocessCodeFile(File.ReadAllText(file), Path.GetFileName(file), preprocessedConstants.ToArray()))
  81. preprocessedFunctions[kv.Key] = kv.Value;
  82. }
  83. catch (Exception ex)
  84. {
  85. lock (Errors)
  86. Errors.Add(new Tuple<ParserError, string>(new ParserError($"Internal pre-process lexer error [{ex}]", new Marker()), Path.GetFileName(file)));
  87. }
  88. #if DEBUG
  89. }
  90. #else
  91. });
  92. #endif
  93. DeclaredProcedures = preprocessedFunctions.ToDictionary(kv => kv.Key, kv => kv.Value);
  94. var declaredFunctions = BaseDefinitions.DefaultGlobalFunctions.ToList();
  95. declaredFunctions.AddRange(DeclaredProcedures.Keys.Where(x => x.IsReturnFunction));
  96. var procedures = DeclaredProcedures.Keys.Where(x => !x.IsReturnFunction).ToList();
  97. Console.WriteLine("Compiling functions...");
  98. #if DEBUG
  99. foreach (var kv in DeclaredFunctions)
  100. #else
  101. Parallel.ForEach(DeclaredProcedures, new ParallelOptions
  102. {
  103. MaxDegreeOfParallelism = Threads
  104. }, kv =>
  105. #endif
  106. {
  107. try
  108. {
  109. var locals = new VariableDictionary();
  110. foreach (var param in kv.Key.Variables)
  111. locals[param.Name] = param.CalculatedValue;
  112. Parser parser = new Parser(kv.Value, kv.Key, declaredFunctions, procedures, globals, locals, BaseDefinitions.DefaultKeywords, csvDefinition, preprocessedConstants.ToArray());
  113. var nodes = parser.Parse(out var localErrors, out var localWarnings);
  114. lock (Errors)
  115. Errors.AddRange(localErrors.Select(x => new Tuple<ParserError, string>(x, $"{kv.Key.Filename} - {kv.Key.Name}")));
  116. lock (Warnings)
  117. Warnings.AddRange(localWarnings.Select(x => new Tuple<ParserError, string>(x, $"{kv.Key.Filename} - {kv.Key.Name}")));
  118. }
  119. catch (Exception ex)
  120. {
  121. lock (Errors)
  122. Errors.Add(new Tuple<ParserError, string>(new ParserError($"Internal post-process lexer error [{ex}]", new Marker()), $"{kv.Key.Filename} - {kv.Key.Name}"));
  123. }
  124. #if DEBUG
  125. }
  126. #else
  127. });
  128. #endif
  129. long fileSize = 0;
  130. int fileCount = 0;
  131. foreach (var file in Directory.EnumerateFiles(InputDirectory, "*.erb", SearchOption.AllDirectories))
  132. {
  133. var info = new FileInfo(file);
  134. fileSize += info.Length;
  135. fileCount++;
  136. }
  137. var htmlWriter = new HTMLWriter
  138. {
  139. Errors = Errors.OrderBy(x => x.Item2).ToList(),
  140. Warnings = Warnings.OrderBy(x => x.Item2).ToList(),
  141. FunctionCount = DeclaredProcedures.Count,
  142. TotalFileSize = fileSize,
  143. TotalFileCount = fileCount
  144. };
  145. using (var stream = File.Create(Path.Combine(outputDirectory, "report.html")))
  146. htmlWriter.WriteReportToFile(stream);
  147. }
  148. }
  149. }