From 62beaa9dc5671fd5af014b1c500470c93ca99109 Mon Sep 17 00:00:00 2001 From: Marc Auberer Date: Fri, 14 Jun 2024 21:27:25 +0200 Subject: [PATCH] Improve driver of bootstrap compiler (#588) --- .run/spice.run.xml | 2 +- media/test-project/test.spice | 31 -------------------- src-bootstrap/driver.spice | 50 ++++++++++++++++++++++----------- src-bootstrap/main.spice | 27 ++++++++---------- src-bootstrap/source-file.spice | 44 +++++++++++++++++++++++++++++ src/typechecker/TypeChecker.cpp | 5 +++- std/os/cmd.spice | 9 ++++++ 7 files changed, 104 insertions(+), 64 deletions(-) diff --git a/.run/spice.run.xml b/.run/spice.run.xml index a3a1adb7a..7f0fcf3e2 100644 --- a/.run/spice.run.xml +++ b/.run/spice.run.xml @@ -1,5 +1,5 @@ - + diff --git a/media/test-project/test.spice b/media/test-project/test.spice index c64567fc7..b2a9cadd8 100644 --- a/media/test-project/test.spice +++ b/media/test-project/test.spice @@ -1,35 +1,4 @@ -type TestStruct struct { - int a -} -p TestStruct.unusedProcedure() { - printf("Hello World: %d", this.a); -} - -f TestStruct.unusedFunction() { - printf("%d", this.a); - return "Hello World"; -} - -f main() { - TestStruct _ts; -} - -/*type Parent struct { - int i -} - -type Child struct { - compose Parent parent - int j - int k -} - -f main() { - Child child; - child.i = 3; - child.j = 5; -}*/ /*import "std/os/env"; import "std/io/filepath"; diff --git a/src-bootstrap/driver.spice b/src-bootstrap/driver.spice index 9c214c391..82e10e75e 100644 --- a/src-bootstrap/driver.spice +++ b/src-bootstrap/driver.spice @@ -120,9 +120,27 @@ public p Driver.enrich() { // Dump AST, IR and symbol table if all debug output is enabled if this.cliOptions.printDebugOutput { - this.cliOptions.dumpAST = true; - this.cliOptions.dumpIR = true; - this.cliOptions.dumpSymbolTable = true; + this.cliOptions.dumpSettings.dumpAST = true; + this.cliOptions.dumpSettings.dumpIR = true; + this.cliOptions.dumpSettings.dumpSymbolTable = true; + } +} + +/** + * Executes the built executable + */ +public p Driver.runBinary() { + // Print status message + if this.cliOptions.printDebugOutput { + print("Running executable ...\n\n"); + } + + // Run executable + FilePath executablePath = this.cliOptions.outputPath; + executablePath.makeNative(); + const int exitCode = execCmd(executablePath.toString()); + if exitCode != 0 { + panic(Error("Your Spice executable exited with non-zero exit code")); } } @@ -131,10 +149,10 @@ public p Driver.enrich() { */ p Driver.addBuildSubcommand() { // Create sub-command itself - CliSubcommand& subCmd = this.cliParser.createSubcommand("build", "Builds your Spice program and emits an executable"); + CliSubcommand& subCmd = this.cliParser.addSubcommand("build", "Builds your Spice program and emits an executable"); subCmd.addAlias("b"); - addCompileSubcommandOptions(subCmd); + this.addCompileSubcommandOptions(subCmd); // --target-triple CliOption& targetOption = subCmd.addOption("--target", this.cliOptions.targetTriple, "Target triple for the emitted executable (for cross-compiling)"); @@ -162,10 +180,10 @@ p Driver.addBuildSubcommand() { */ p Driver.addRunSubcommand() { // Create sub-command itself - CliSubcommand& subCmd = this.cliParser.createSubcommand("run", "Builds your Spice program and runs it immediately"); + CliSubcommand& subCmd = this.cliParser.addSubcommand("run", "Builds your Spice program and runs it immediately"); subCmd.addAlias("r"); - addCompileSubcommandOptions(subCmd); + this.addCompileSubcommandOptions(subCmd); // --output CliOption& outputOption = subCmd.addOption("--output", this.cliOptions.outputPath, "Set the output file path"); @@ -182,10 +200,10 @@ p Driver.addRunSubcommand() { */ p Driver.addInstallSubcommand() { // Create sub-command itself - CliSubcommand& subCmd = this.cliParser.createSubcommand("install", "Builds your Spice program and installs it to a directory in the PATH variable"); + CliSubcommand& subCmd = this.cliParser.addSubcommand("install", "Builds your Spice program and installs it to a directory in the PATH variable"); subCmd.addAlias("i"); - addCompileSubcommandOptions(subCmd); + this.addCompileSubcommandOptions(subCmd); } /** @@ -193,10 +211,10 @@ p Driver.addInstallSubcommand() { */ p Driver.addUninstallSubcommand() { // Create sub-command itself - CliSubcommand& subCmd = this.cliParser.createSubcommand("uninstall", "Builds your Spice program and runs it immediately"); + CliSubcommand& subCmd = this.cliParser.addSubcommand("uninstall", "Builds your Spice program and runs it immediately"); subCmd.addAlias("u"); - addCompileSubcommandOptions(subCmd); + this.addCompileSubcommandOptions(subCmd); } p Driver.addCompileSubcommandOptions(CliSubcommand& subCmd) { @@ -204,19 +222,19 @@ p Driver.addCompileSubcommandOptions(CliSubcommand& subCmd) { CliOption& debugOutputFlag = subCmd.addFlag("--debug-output", this.cliOptions.printDebugOutput, "Enable debug output"); debugOutputFlag.addAlias("-d"); // --dump-cst - CliOption& dumpCstFlag = subCmd.addFlag("--dump-cst", this.cliOptions.dumpCST, "Dump CSTs as serialized string and SVG image"); + CliOption& dumpCstFlag = subCmd.addFlag("--dump-cst", this.cliOptions.dumpSettings.dumpCST, "Dump CSTs as serialized string and SVG image"); dumpCstFlag.addAlias("-cst"); // --dump-ast - CliOption& dumpAstFlag = subCmd.addFlag("--dump-ast", this.cliOptions.dumpAST, "Dump ASTs as serialized string and SVG image"); + CliOption& dumpAstFlag = subCmd.addFlag("--dump-ast", this.cliOptions.dumpSettings.dumpAST, "Dump ASTs as serialized string and SVG image"); dumpAstFlag.addAlias("-ast"); // --dump-symtab - CliOption& dumpSymtabFlag = subCmd.addFlag("--dump-symtab", this.cliOptions.dumpSymbolTable, "Dump serialized symbol tables"); + CliOption& dumpSymtabFlag = subCmd.addFlag("--dump-symtab", this.cliOptions.dumpSettings.dumpSymbolTable, "Dump serialized symbol tables"); dumpSymtabFlag.addAlias("-symtab"); // --dump-ir - CliOption& dumpIrFlag = subCmd.addFlag("--dump-ir", this.cliOptions.dumpIR, "Dump LLVM-IR"); + CliOption& dumpIrFlag = subCmd.addFlag("--dump-ir", this.cliOptions.dumpSettings.dumpIR, "Dump LLVM-IR"); dumpIrFlag.addAlias("-ir"); // --dump-assembly - CliOption& dumpAsmFlag = subCmd.addFlag("--dump-assembly", this.cliOptions.dumpAssembly, "Dump assembly code"); + CliOption& dumpAsmFlag = subCmd.addFlag("--dump-assembly", this.cliOptions.dumpSettings.dumpAssembly, "Dump assembly code"); dumpAsmFlag.addAlias("-asm"); dumpAsmFlag.addAlias("-s"); diff --git a/src-bootstrap/main.spice b/src-bootstrap/main.spice index 39e2e3ee8..bd7553eef 100644 --- a/src-bootstrap/main.spice +++ b/src-bootstrap/main.spice @@ -2,9 +2,9 @@ import "std/os/os"; // Own imports -import "./source-file"; -import "./driver"; -import "./global/global-resource-manager"; +//import "bootstrap/source-file"; +import "bootstrap/driver"; +//import "bootstrap/global/global-resource-manager"; /** * Compile main source file. All files, that are included by the main source file will be resolved recursively. @@ -14,10 +14,10 @@ import "./global/global-resource-manager"; */ f compileProject(const CliOptions& cliOptions) { // Instantiate GlobalResourceManager - dyn resourceManager = GlobalResourceManager(options); + /*dyn resourceManager = GlobalResourceManager(cliOptions); // Create source file instance for main source file - SourceFile* mainSourceFile = resourceManager.createSourceFile(nullptr, MAIN_FILE_NAME, cliOptions.mainSourceFile, false); + heap SourceFile* mainSourceFile = resourceManager.createSourceFile(nil, String(MAIN_FILE_NAME), cliOptions.mainSourceFile, false); // Run compile pipeline for main source file. All dependent source files are triggered by their parents mainSourceFile.runFrontEnd(); @@ -29,10 +29,7 @@ f compileProject(const CliOptions& cliOptions) { resourceManager.linker.link(); // Print compiler warnings - mainSourceFile.collectAndPrintWarnings(); - - // Print compiler warnings - mainSourceFile.collectAndPrintWarnings(); + mainSourceFile.collectAndPrintWarnings();*/ return true; } @@ -47,22 +44,22 @@ f compileProject(const CliOptions& cliOptions) { f main(int argc, string[] argv) { // Initialize command line parser Driver driver; - driver.create(); + driver.init(); const int exitCode = driver.parse(argc, argv); - if exitCode != EXIT_SUCCESS { + if exitCode != EXIT_CODE_SUCCESS { return exitCode; } // Cancel here if we do not have to compile if !driver.shouldCompile { - return EXIT_SUCCESS; + return EXIT_CODE_SUCCESS; } driver.enrich(); // Prepare the cli options // Kick off the compiling process if !compileProject(driver.cliOptions) { - return EXIT_FAILURE; + return EXIT_CODE_ERROR; } // Execute @@ -70,5 +67,5 @@ f main(int argc, string[] argv) { driver.runBinary(); } - return EXIT_SUCCESS; -} \ No newline at end of file + return EXIT_CODE_SUCCESS; +} diff --git a/src-bootstrap/source-file.spice b/src-bootstrap/source-file.spice index 5a6074cb0..d2b32f644 100644 --- a/src-bootstrap/source-file.spice +++ b/src-bootstrap/source-file.spice @@ -591,3 +591,47 @@ public f SourceFile.getNameRegistryEntry(const String& return entry; } + +public p SourceFile.checkForSoftErrors() { + // Check if there are any soft errors and if so, print them + if !this.resourceManager.errorManager.softErrors.isEmpty() { + String errorMessage = String("There are unresolved errors. Please fix them and recompile."); + foreach dyn error : this.resourceManager.errorManager.softErrors { + errorMessage += "\n\n"; + errorMessage += error.toString(); + } + panic(Error("Compilation aborted due to unresolved errors.")); + } +} + +public p SourceFile.collectAndPrintWarnings() { + // Print warnings for all dependencies + foreach dyn dependency : this.dependencies { + SourceFile* sourceFile = dependency.getSecond(); + if !sourceFile.isStdFile { + sourceFile.collectAndPrintWarnings(); + } + } + // Collect warnings for this file + if !ignoreWarnings { + this.globalScope.collectWarnings(this.compilerOutput.warnings); + } + // Print warnings for this file + foreach dyn warning : this.compilerOutput.warnings { + warning.print(); + } +} + +public f SourceFile.getRootSourceFile() { + return this.isMainFile ? this : this.parent.getRootSourceFile(); +} + +/*public f SourceFile.isRT(RuntimeModule runtimeModule) { + assert IDENTIFIER_RUNTIME_MODULES.contains(runtimeModule); + const string topLevelName = IDENTIFIER_RUNTIME_MODULES.at(runtimeModule); + if !this.exportedNameRegistry.contains(topLevelName) { + return false; + } + dyn entry = this.exportedNameRegistry.get(topLevelName); + return entry.targetEntry.scope == this.globalScope; +}*/ diff --git a/src/typechecker/TypeChecker.cpp b/src/typechecker/TypeChecker.cpp index 3b159839e..32cb0bb0e 100644 --- a/src/typechecker/TypeChecker.cpp +++ b/src/typechecker/TypeChecker.cpp @@ -1776,7 +1776,10 @@ std::any TypeChecker::visitFctCall(FctCallNode *node) { Scope *matchScope = returnBaseType.getBodyScope()->parent; assert(matchScope != nullptr); Struct *spiceStruct = StructManager::matchStruct(matchScope, structName, returnBaseType.getTemplateTypes(), node); - assert(spiceStruct != nullptr); + if (!spiceStruct) { + const std::string signature = Struct::getSignature(structName, returnBaseType.getTemplateTypes()); + SOFT_ERROR_ER(node, UNKNOWN_DATATYPE, "Could not find struct candidate for struct '" + signature + "'. Do the template types match?") + } returnType = returnType.getWithBodyScope(spiceStruct->scope).replaceBaseType(returnBaseType); returnType = mapImportedScopeTypeToLocalType(returnType.getBase().getBodyScope(), returnType); diff --git a/std/os/cmd.spice b/std/os/cmd.spice index 3377cd4e9..e8f40f769 100644 --- a/std/os/cmd.spice +++ b/std/os/cmd.spice @@ -18,4 +18,13 @@ public f getPID() { */ public f execCmd(string cmd) { return system(cmd); +} + +/** + * Executes a shell command by creating a new process. + * + * @return Return code of the shell comand + */ +public f execCmd(const String& cmd) { + return system(cmd.getRaw()); } \ No newline at end of file