static void Main(string?programName = null, string[]?args = null) { var tracer = new Tracer(); tracer.Restart(); if (args == null) { throw new InvalidOperationException("You must pass in a file"); } var libraries = args.Where(x => { var ext = Path.GetExtension(x); return(ext == ".exe" || ext == ".dll"); }).ToArray(); args = args.Except(libraries).ToArray(); if (args.Length == 0) { throw new InvalidOperationException("You must pass in a file to actually compile"); } #pragma warning disable CS8619 // Nullability of reference types in value doesn't match target type. Assembly[] assemblies = libraries.Select(x => { try { return(Assembly.LoadFrom(x)); } #pragma warning disable CA1031 // Do not catch general exception types catch #pragma warning restore CA1031 // Do not catch general exception types { return(null); } }).Where(x => x != null).Append(typeof(object).Assembly).ToArray(); #pragma warning restore CS8619 // Nullability of reference types in value doesn't match target type. if (programName == null) { programName = Path.GetFileNameWithoutExtension(args[0]); } tracer.AddEpoch("Initialization"); var tokenizer = new SimpleTokenizer(); var parser = new SimpleParser(); var rootNodes = new List <ImmutableRootSyntaxNode>(); foreach (var file in args) { var code = File.ReadAllText(file); var fileTokens = tokenizer.EnumerateTokens(code.AsSpan()); tracer.AddEpoch($"Tokenizing {file}"); var immutableNode = parser.ParseTokens(fileTokens); rootNodes.Add(immutableNode); tracer.AddEpoch($"Parsing {file}"); } EmitMain(programName + "Emit", assemblies, tracer, rootNodes); // Skip the ilasm backend for demonstation. IlAsmMain(programName, assemblies, tracer, rootNodes); tracer.PrintEpochs(); Console.WriteLine("Compilation Complete!"); }