|
@@ -1,12 +1,16 @@
|
|
|
using System;
|
|
|
using System.Collections.Concurrent;
|
|
|
using System.Collections.Generic;
|
|
|
+using System.Diagnostics;
|
|
|
+using System.Drawing;
|
|
|
using System.IO;
|
|
|
using System.Linq;
|
|
|
using System.Runtime;
|
|
|
using System.Text;
|
|
|
using System.Threading.Tasks;
|
|
|
+using NTERA.Core;
|
|
|
using NTERA.Engine.Compiler;
|
|
|
+using NTERA.Engine.Runtime.Resources;
|
|
|
|
|
|
namespace NTERA.Engine.Runtime
|
|
|
{
|
|
@@ -17,48 +21,80 @@ namespace NTERA.Engine.Runtime
|
|
|
public ICollection<FunctionVariable> DefinedConstants { get; protected set; }
|
|
|
public CSVDefinition CSVDefinition { get; protected set; }
|
|
|
|
|
|
+ protected Dictionary<string, ImageDefinition> ImageDefinitions { get; set; }
|
|
|
+
|
|
|
protected Dictionary<FunctionDefinition, string> ProcedureFiles { get; set; }
|
|
|
public Dictionary<FunctionDefinition, ExecutionNode[]> CompiledProcedures { get; protected set; } = new Dictionary<FunctionDefinition, ExecutionNode[]>();
|
|
|
|
|
|
public string InputDirectory { get; }
|
|
|
+ protected string CSVPath { get; set; }
|
|
|
+ protected string ERBPath { get; set; }
|
|
|
+ protected string ResourcePath { get; set; }
|
|
|
|
|
|
public static int Threads = 4;
|
|
|
|
|
|
public JITCompiler(string path)
|
|
|
{
|
|
|
InputDirectory = path;
|
|
|
-
|
|
|
- Compile();
|
|
|
}
|
|
|
|
|
|
- protected void Compile()
|
|
|
+ public void Initialize(IConsole console)
|
|
|
{
|
|
|
- string csvPath = Path.Combine(InputDirectory, "CSV");
|
|
|
- string erbPath = Path.Combine(InputDirectory, "ERB");
|
|
|
+ Stopwatch stopwatch = new Stopwatch();
|
|
|
+ stopwatch.Start();
|
|
|
+
|
|
|
+ CSVPath = Path.Combine(InputDirectory, "CSV");
|
|
|
+ ERBPath = Path.Combine(InputDirectory, "ERB");
|
|
|
+ ResourcePath = Path.Combine(InputDirectory, "resources");
|
|
|
|
|
|
- var csvDefinition = new CSVDefinition();
|
|
|
+ CSVDefinition = new CSVDefinition();
|
|
|
+ ImageDefinitions = new Dictionary<string, ImageDefinition>();
|
|
|
|
|
|
- Console.WriteLine("Preprocessing CSV files...");
|
|
|
+ console.PrintSystemLine("Preprocessing CSV files...");
|
|
|
|
|
|
|
|
|
- foreach (var file in Directory.EnumerateFiles(csvPath, "*.csv", SearchOption.AllDirectories))
|
|
|
+ foreach (var file in Directory.EnumerateFiles(CSVPath, "*.csv", SearchOption.AllDirectories))
|
|
|
{
|
|
|
- string path = Path.GetFileNameWithoutExtension(file);
|
|
|
+ string localName = Path.GetFileNameWithoutExtension(file);
|
|
|
|
|
|
- if (path.EndsWith("_TR"))
|
|
|
+ if (localName == null || localName.EndsWith("_TR"))
|
|
|
continue;
|
|
|
|
|
|
- Preprocessor.ProcessCSV(csvDefinition, path, File.ReadLines(file, Encoding.UTF8));
|
|
|
+ Preprocessor.ProcessCSV(CSVDefinition, localName, File.ReadLines(file, Encoding.UTF8));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ foreach (var file in Directory.EnumerateFiles(ResourcePath, "*.csv", SearchOption.TopDirectoryOnly))
|
|
|
+ {
|
|
|
+ foreach (var line in Preprocessor.SplitCSV(File.ReadLines(file)))
|
|
|
+ {
|
|
|
+ if (line.Count != 2 && line.Count != 6)
|
|
|
+ throw new ParserException($"Unable to parse resource CSV file '{Path.GetFileName(file)}'");
|
|
|
+
|
|
|
+ ImageDefinition definition = new ImageDefinition
|
|
|
+ {
|
|
|
+ Name = line[0],
|
|
|
+ Filename = line[1],
|
|
|
+ Dimensions = null
|
|
|
+ };
|
|
|
+
|
|
|
+ if (line.Count == 6)
|
|
|
+ {
|
|
|
+ definition.Dimensions = new Rectangle(int.Parse(line[2]), int.Parse(line[3]), int.Parse(line[4]), int.Parse(line[5]));
|
|
|
+ }
|
|
|
+
|
|
|
+ ImageDefinitions[definition.Name] = definition;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- Console.WriteLine("Preprocessing header files...");
|
|
|
+ console.PrintSystemLine("Preprocessing header files...");
|
|
|
|
|
|
ConcurrentBag<FunctionVariable> preprocessedConstants = new ConcurrentBag<FunctionVariable>();
|
|
|
|
|
|
#if DEBUG
|
|
|
- foreach (var file in Directory.EnumerateFiles(erbPath, "*.erh", SearchOption.AllDirectories))
|
|
|
+ foreach (var file in Directory.EnumerateFiles(ERBPath, "*.erh", SearchOption.AllDirectories))
|
|
|
#else
|
|
|
- Parallel.ForEach(Directory.EnumerateFiles(erbPath, "*.erh", SearchOption.AllDirectories), new ParallelOptions
|
|
|
+ Parallel.ForEach(Directory.EnumerateFiles(ERBPath, "*.erh", SearchOption.AllDirectories), new ParallelOptions
|
|
|
{
|
|
|
MaxDegreeOfParallelism = Threads
|
|
|
}, file =>
|
|
@@ -74,15 +110,15 @@ namespace NTERA.Engine.Runtime
|
|
|
|
|
|
DefinedConstants = preprocessedConstants.ToArray();
|
|
|
|
|
|
- Console.WriteLine("Preprocessing functions...");
|
|
|
+ console.PrintSystemLine("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))
|
|
|
+ foreach (var file in Directory.EnumerateFiles(ERBPath, "*.erb", SearchOption.AllDirectories))
|
|
|
#else
|
|
|
- Parallel.ForEach(Directory.EnumerateFiles(erbPath, "*.erb", SearchOption.AllDirectories), new ParallelOptions
|
|
|
+ Parallel.ForEach(Directory.EnumerateFiles(ERBPath, "*.erb", SearchOption.AllDirectories), new ParallelOptions
|
|
|
{
|
|
|
MaxDegreeOfParallelism = Threads
|
|
|
}, file =>
|
|
@@ -104,8 +140,13 @@ namespace NTERA.Engine.Runtime
|
|
|
declaredFunctions.AddRange(DefinedProcedures.Where(x => x.IsReturnFunction));
|
|
|
DefinedFunctions = declaredFunctions;
|
|
|
|
|
|
+ console.PrintSystemLine("Compacting memory...");
|
|
|
+
|
|
|
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
|
|
|
GC.Collect();
|
|
|
+
|
|
|
+ stopwatch.Stop();
|
|
|
+ console.PrintSystemLine($"Completed initialization in {stopwatch.ElapsedMilliseconds}ms");
|
|
|
}
|
|
|
|
|
|
public IEnumerable<ExecutionNode> GetExecutionNodes(FunctionDefinition function)
|
|
@@ -127,5 +168,22 @@ namespace NTERA.Engine.Runtime
|
|
|
|
|
|
return nodes;
|
|
|
}
|
|
|
+
|
|
|
+ protected Dictionary<string, Bitmap> BitmapCache = new Dictionary<string, Bitmap>();
|
|
|
+
|
|
|
+ public Bitmap GetImage(string imageName, out ImageDefinition definition)
|
|
|
+ {
|
|
|
+ definition = ImageDefinitions[imageName];
|
|
|
+
|
|
|
+ string filename = Path.Combine(ResourcePath, definition.Filename);
|
|
|
+
|
|
|
+ if (!BitmapCache.TryGetValue(filename, out var bitmap))
|
|
|
+ {
|
|
|
+ bitmap = new Bitmap(filename);
|
|
|
+ BitmapCache.Add(filename, bitmap);
|
|
|
+ }
|
|
|
+
|
|
|
+ return bitmap;
|
|
|
+ }
|
|
|
}
|
|
|
}
|