| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright (c) 2021-2025 ChilliBits. All rights reserved. | ||
| 2 | |||
| 3 | #include <SourceFile.h> | ||
| 4 | #include <driver/Driver.h> | ||
| 5 | #include <exception/CliError.h> | ||
| 6 | #include <exception/LexerError.h> | ||
| 7 | #include <exception/LinkerError.h> | ||
| 8 | #include <exception/ParserError.h> | ||
| 9 | #include <exception/SemanticError.h> | ||
| 10 | #include <global/GlobalResourceManager.h> | ||
| 11 | #include <typechecker/MacroDefs.h> | ||
| 12 | |||
| 13 | using namespace spice::compiler; | ||
| 14 | |||
| 15 | /** | ||
| 16 | * Compile main source file. All files, that are included by the main source file will be resolved recursively. | ||
| 17 | * | ||
| 18 | * @param cliOptions Command line options | ||
| 19 | * @return Successful or not | ||
| 20 | */ | ||
| 21 | ✗ | bool compileProject(const CliOptions &cliOptions) { | |
| 22 | try { | ||
| 23 | // Instantiate GlobalResourceManager | ||
| 24 | ✗ | GlobalResourceManager resourceManager(cliOptions); | |
| 25 | |||
| 26 | // Create source file instance for main source file | ||
| 27 | ✗ | SourceFile *mainSourceFile = resourceManager.createSourceFile(nullptr, MAIN_FILE_NAME, cliOptions.mainSourceFile, false); | |
| 28 | |||
| 29 | // Run compile pipeline for main source file. All dependent source files are triggered by their parents | ||
| 30 | ✗ | mainSourceFile->runFrontEnd(); | |
| 31 | ✗ | CHECK_ABORT_FLAG_B() | |
| 32 | ✗ | mainSourceFile->runMiddleEnd(); | |
| 33 | ✗ | CHECK_ABORT_FLAG_B() | |
| 34 | ✗ | mainSourceFile->runBackEnd(); | |
| 35 | ✗ | CHECK_ABORT_FLAG_B() | |
| 36 | |||
| 37 | // Link the target executable (link object files to executable) | ||
| 38 | ✗ | resourceManager.linker.prepare(); | |
| 39 | ✗ | resourceManager.linker.link(); | |
| 40 | |||
| 41 | // Print compiler warnings | ||
| 42 | ✗ | mainSourceFile->collectAndPrintWarnings(); | |
| 43 | |||
| 44 | ✗ | return true; | |
| 45 | ✗ | } catch (LexerError &e) { | |
| 46 | ✗ | std::cout << e.what() << "\n"; | |
| 47 | ✗ | } catch (ParserError &e) { | |
| 48 | ✗ | std::cout << e.what() << "\n"; | |
| 49 | ✗ | } catch (SemanticError &e) { | |
| 50 | ✗ | std::cout << e.what() << "\n"; | |
| 51 | ✗ | } catch (CompilerError &e) { | |
| 52 | ✗ | std::cout << e.what() << "\n"; | |
| 53 | ✗ | } catch (LinkerError &e) { | |
| 54 | ✗ | std::cout << e.what() << "\n"; | |
| 55 | ✗ | } | |
| 56 | ✗ | return false; | |
| 57 | } | ||
| 58 | |||
| 59 | /** | ||
| 60 | * Entry point to the Spice compiler | ||
| 61 | * | ||
| 62 | * @param argc Argument count | ||
| 63 | * @param argv Argument vector | ||
| 64 | * @return Return code | ||
| 65 | */ | ||
| 66 | ✗ | int main(int argc, const char *argv[]) { | |
| 67 | // Initialize command line parser | ||
| 68 | ✗ | Driver driver; | |
| 69 | ✗ | driver.init(); | |
| 70 | try { | ||
| 71 | ✗ | if (const int exitCode = driver.parse(argc, argv); exitCode != EXIT_SUCCESS) | |
| 72 | ✗ | return exitCode; | |
| 73 | |||
| 74 | // Cancel here if we do not have to compile | ||
| 75 | ✗ | if (!driver.shouldCompile) | |
| 76 | ✗ | return EXIT_SUCCESS; | |
| 77 | |||
| 78 | ✗ | driver.enrich(); // Prepare the cli options | |
| 79 | |||
| 80 | // Kick off the compilation process | ||
| 81 | ✗ | if (!compileProject(driver.cliOptions)) | |
| 82 | ✗ | return EXIT_FAILURE; | |
| 83 | |||
| 84 | // Execute | ||
| 85 | ✗ | if (driver.cliOptions.execute) | |
| 86 | ✗ | driver.runBinary(); | |
| 87 | |||
| 88 | ✗ | return EXIT_SUCCESS; | |
| 89 | ✗ | } catch (CliError &e) { | |
| 90 | ✗ | std::cout << e.what() << "\n"; | |
| 91 | ✗ | return EXIT_FAILURE; | |
| 92 | ✗ | } | |
| 93 | ✗ | } | |
| 94 |