123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Runtime;
- using System.Text;
- using System.Threading.Tasks;
- using NTERA.Engine.Compiler;
- namespace NTERA.Engine.Runtime
- {
- public class JITCompiler : IExecutionProvider
- {
- public ICollection<FunctionDefinition> DefinedProcedures { get; protected set; }
- public ICollection<FunctionDefinition> DefinedFunctions { get; protected set; }
- public ICollection<FunctionVariable> DefinedConstants { get; protected set; }
- public CSVDefinition CSVDefinition { get; protected set; }
- protected Dictionary<FunctionDefinition, string> ProcedureFiles { get; set; }
- public Dictionary<FunctionDefinition, ExecutionNode[]> CompiledProcedures { get; protected set; } = new Dictionary<FunctionDefinition, ExecutionNode[]>();
- public string InputDirectory { get; }
- public static int Threads = 4;
- public JITCompiler(string path)
- {
- InputDirectory = path;
- Compile();
- }
- protected void Compile()
- {
- 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
- {
- foreach (var variable in Preprocessor.PreprocessHeaderFile(File.ReadAllText(file)))
- preprocessedConstants.Add(variable);
- #if DEBUG
- }
- #else
- });
- #endif
- DefinedConstants = preprocessedConstants.ToArray();
- Console.WriteLine("Preprocessing functions...");
- ProcedureFiles = new Dictionary<FunctionDefinition, string>();
- 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
- {
- foreach (var kv in Preprocessor.PreprocessCodeFile(File.ReadAllText(file), Path.GetFileName(file), DefinedConstants))
- {
- preprocessedFunctions[kv.Key] = kv.Value;
- ProcedureFiles[kv.Key] = file;
- }
- #if DEBUG
- }
- #else
- });
- #endif
- DefinedProcedures = preprocessedFunctions.Select(kv => kv.Key).ToArray();
- var declaredFunctions = BaseDefinitions.DefaultGlobalFunctions.ToList();
- declaredFunctions.AddRange(DefinedProcedures.Where(x => x.IsReturnFunction));
- DefinedFunctions = declaredFunctions;
- GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
- GC.Collect();
- }
- public IEnumerable<ExecutionNode> GetExecutionNodes(FunctionDefinition function)
- {
- if (CompiledProcedures.ContainsKey(function))
- return CompiledProcedures[function];
- string filename = ProcedureFiles[function];
- var preprocessed = Preprocessor.PreprocessCodeFile(File.ReadAllText(filename), Path.GetFileName(filename), DefinedConstants);
- Parser parser = new Parser(preprocessed.Single(x => x.Key.Name == function.Name).Value, function, DefinedFunctions, DefinedProcedures.Where(x => !x.IsReturnFunction).ToArray(), BaseDefinitions.DefaultGlobalVariables, function.Variables, BaseDefinitions.DefaultKeywords, CSVDefinition, DefinedConstants);
- var nodes = parser.Parse(out var localErrors, out var localWarnings)?.ToArray();
- if (localErrors.Count > 0)
- throw new ParserException($"Failed to compile '{function.Name}'");
- CompiledProcedures.Add(function, nodes);
- return nodes;
- }
- }
- }
|