/// <summary> /// Sets up the compiler instance with all needed components. /// </summary> /// <param name="loggerFactory">A logger factory to use to instantiate loggers.</param> public CobaltCompiler(ILoggerFactory loggerFactory, ITargetCodeGenerator compilerBackend) { Logger = loggerFactory.CreateLogger <CobaltCompiler>(); Lexer = new CobaltLexer(loggerFactory); Parser = new CobaltParser(loggerFactory); Optimizer = new CobaltOptimizer(loggerFactory); Analyzer = new CobaltSemanticAnalyzer(loggerFactory); TargetCodeGenerator = compilerBackend; }
/// <summary> /// The compiler entry point. /// </summary> /// <param name="args">Command line arguments.</param> public static void Main(string[] args) { // Set up configuration from command line arguments IConfiguration configuration = new ConfigurationBuilder().AddCommandLine(args, new Dictionary <string, string>() { { "-i", ARG_INPUT_FILE }, { "-o", ARG_OUTPUT_DIR }, { "-t", ARG_TARGET_PLATFORM } }).Build(); // Check for verbose mode bool verbose = args.Contains("-v"); // Set up logging providers ILoggerFactory loggerFactory = LoggingBootstrapper.CreateLoggerFactory(verbose); // Logger for local logging ILogger logger = loggerFactory.CreateLogger <Program>(); // Display help if requested if (args.Contains("-h")) { PrintHelpAndExit(logger); } // Parse command line arguments string inputFile = configuration.GetValue <string>(ARG_INPUT_FILE); string outputDir = configuration.GetValue <string>(ARG_OUTPUT_DIR); string targetPlatform = configuration.GetValue <string>(ARG_TARGET_PLATFORM); // Validate required parameters if (string.IsNullOrWhiteSpace(inputFile) || string.IsNullOrWhiteSpace(outputDir) || string.IsNullOrWhiteSpace(targetPlatform)) { logger.LogCritical("One or more required parameter is missing!"); PrintHelpAndExit(logger); } // Display information in verbose mode logger.LogDebug("Compiler parameters:"); logger.LogDebug($" - Input file: {inputFile}"); logger.LogDebug($" - Output directory: {outputDir}"); logger.LogDebug($" - Target platform: {targetPlatform}"); // Set up compiler backend ITargetCodeGenerator backend = null; switch (targetPlatform.ToLowerInvariant()) { case "node": case "Node": backend = new NodeJavaScriptCodeGenerator(); break; default: logger.LogError($"Unknown target platform `{targetPlatform}`."); break; } if (backend != null) { try { // Set up compiler CobaltCompiler compiler = new CobaltCompiler(loggerFactory, backend); // Read source code from input file string sourceCode = File.ReadAllText(inputFile); // Compile! logger.LogInformation("Compiling program..."); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); TargetProgram targetProgram = compiler.Compile(sourceCode); stopwatch.Stop(); logger.LogInformation($"Successfully compiled program in {stopwatch.ElapsedMilliseconds} ms."); // Write output files if (!Directory.Exists(outputDir)) { Directory.CreateDirectory(outputDir); } logger.LogInformation($"Writing files to {outputDir}..."); foreach (ITargetFile file in targetProgram.GetFiles()) { string filePath = Path.Combine(outputDir, file.Name); file.Writer.WriteTargetFile(file, filePath); logger.LogDebug($" - Wrote file {file.Name}"); } logger.LogInformation("All files have been written to disk."); } catch (Exception exception) { if (verbose) { logger.LogError($"Compilation failed with {exception.Message}{Environment.NewLine}{exception.StackTrace}"); } else { logger.LogError("Compilation failed.", exception); } logger.LogInformation("Press any key to terminate..."); Console.ReadKey(); } } }