private static void Main(string[] args) { if (args.Length < 1 || args.Any(arg => !File.Exists(arg))) { Console.WriteLine( $"Usage {Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().Location)} codefile.llama [, codefile2.llama, ...]" ); } var time = Stopwatch.StartNew(); var sourceFilePath = args[0]; var source = string.Join("\n", args.Select(File.ReadAllText)); var lexer = LexerBuilder.BuildLlamaLexer(); var parser = new ParseContext(LlamaParseStore.Instance, lexer, source); var document = parser.ReadNode <LlamaDocument>(); Console.WriteLine($"Parsing time: {time.Elapsed.TotalMilliseconds:F2} ms"); time.Restart(); var functionDeclarations = document.Functions.Select(fun => fun.Declaration).ToArray(); var compiler = new Compiler(new LlamaCompilerStore(), new LinkerFactory(), document.Imports, functionDeclarations); foreach (var functionImplementation in document.Functions) { compiler.AddFunction(functionImplementation); } var codeBlob = compiler.Code; var linker = (Linker)compiler.LinkingInfo; Console.WriteLine($"Compilation time: {time.Elapsed.TotalMilliseconds:F2} ms"); time.Restart(); var pe32PlusExeBuilder = new ExecutableBuilder { Subsystem = Subsystem.WindowsCui // Change to WindowsGui to make a Window application (without console) }; linker.LinkPreBuild(pe32PlusExeBuilder); var mainOffset = linker.GetCodeOffsetOfKnownFunction("Main"); if (mainOffset < 0) { Console.WriteLine("No main function"); return; } pe32PlusExeBuilder.AddAdditionalSection("A\nB\t\0", 200, SectionCharacteristics.MemWrite | SectionCharacteristics.MemRead); var peResult = pe32PlusExeBuilder.Build((uint)codeBlob.Length, (uint)mainOffset); codeBlob.CopyTo(peResult.GetCodeSectionBuffer()); linker.LinkPostBuild(peResult); Console.WriteLine($"Linking time: {time.Elapsed.TotalMilliseconds:F2} ms"); time.Restart(); using var fileStream = File.Open(Path.ChangeExtension(sourceFilePath, "exe"), FileMode.Create); peResult.Finish(fileStream); }