From 0e5a864b2a52dc52c6807ad0f976d4dd3677d6ea Mon Sep 17 00:00:00 2001 From: Marc Auberer Date: Thu, 15 Sep 2022 01:18:53 +0200 Subject: [PATCH 1/5] Add linked list, doubly linked list and binary tree data types in std --- .run/Spice_run.run.xml | 2 +- media/test-project/os-test.spice | 20 +++++++- std/data/binary-tree.spice | 51 +++++++++++++++++++ std/data/doubly-linked-list.spice | 81 +++++++++++++++++++++++++++++++ std/data/linked-list.spice | 75 ++++++++++++++++++++++++++++ 5 files changed, 227 insertions(+), 2 deletions(-) create mode 100644 std/data/binary-tree.spice create mode 100644 std/data/doubly-linked-list.spice create mode 100644 std/data/linked-list.spice diff --git a/.run/Spice_run.run.xml b/.run/Spice_run.run.xml index 67ebee1e4..77c4d605a 100644 --- a/.run/Spice_run.run.xml +++ b/.run/Spice_run.run.xml @@ -1,5 +1,5 @@ - + diff --git a/media/test-project/os-test.spice b/media/test-project/os-test.spice index a5e374d34..ba3ee61af 100644 --- a/media/test-project/os-test.spice +++ b/media/test-project/os-test.spice @@ -17,7 +17,7 @@ f main() { server.serve("/test", "Hello World!"); }*/ -import "std/runtime/string_rt" as _rt_str; +/*import "std/runtime/string_rt" as _rt_str; f main() { //_rt_str::String s = _rt_str::String("Test"); @@ -34,4 +34,22 @@ f main() { string s3 = 2 * 'c' * 7; printf("Result: %s\n", s3); //printf("%s", s1 + s2); +}*/ + +//import "std/data/linked-list" as ll; + +public f src(bool x, bool y) { + return 0 == ((x ? 1 : 8) & (y ? 1 : 8)); +} + +public f tgt(int x, int y) { + return x ^ y; +} + +f main() { + printf("Result: %d, %d", src(false, true), tgt(0, 1)); + + /*ll::LinkedList linkedList = ll::LinkedList(); + linkedList.insert(12s); + linkedList.insert(5s);*/ } \ No newline at end of file diff --git a/std/data/binary-tree.spice b/std/data/binary-tree.spice new file mode 100644 index 000000000..869266ab2 --- /dev/null +++ b/std/data/binary-tree.spice @@ -0,0 +1,51 @@ +// Link external functions +ext malloc(long); +ext free(byte*); + +// Add generic type definitions +type T dyn; + +/** + * Node of a BinaryTree + */ +public type Node struct { + Node* childLeft + Node* childRight + T value +} + +/** + * A binary tree is a data structure to fasten up search speeds. Binary trees (when balanced) can be searched in O(log n). + * Insert operations, on the other hand, are rather slow, because the tree might get re-balanced. + */ +public type BinaryTree struct { + Node* rootNode + bool isBalanced +} + +public p BinaryTree.ctor() { + this.rootNode = nil*>; + this.isBalanced = false; +} + +public p BinaryTree.dtor() { + if this.rootNode != nil*> { + this.rootNode.dtor(); + free((byte*) this.rootNode); + } +} + +public p Node.dtor() { + if this.childLeft != nil*> { + this.childLeft.dtor(); + free((byte*) this.childLeft); + } + if this.childRight != nil*> { + this.childRight.dtor(); + free((byte*) this.childRight); + } +} + +public p BinaryTree.insert(T newValue, Node* baseNode = nil*>) { + // Search position where to insert +} \ No newline at end of file diff --git a/std/data/doubly-linked-list.spice b/std/data/doubly-linked-list.spice new file mode 100644 index 000000000..51f075f04 --- /dev/null +++ b/std/data/doubly-linked-list.spice @@ -0,0 +1,81 @@ +// Link external functions +ext malloc(long); +ext free(byte*); + +// Add generic type definitions +type T dyn; + +/** + * Node of a DoublyLinkedList + */ +public type Node struct { + Node* prev + T value + Node* next +} + +/** + * A doubly linked list is a common, dynamically resizable data structure to store uniform data in order. + * It is characterized by the pointer for every item, pointing to the next one and the pointer, pointing + * to the previous one. + */ +public type DoublyLinkedList struct { + Node* head + Node* tail +} + +public p Node.dtor() { + if this.next != nil*> { + this.next.dtor(); + free((byte*) this.next); + } +} + +public p DoublyLinkedList.insert(T newValue, Node* prevNode = nil*>) { + // Create new node + Node* newNode; + unsafe { + newNode = (Node*) malloc(sizeof(type Node)); + } + newNode.value = newValue; + + if prevNode != nil*> { // Previous node was passed -> insert after this node + // Link the previous to this one + newNode.prev = prevNode; + // Link the next node to this one + newNode.next = prevNode.next; + // Link this node to the next node + prevNode.next.prev = newNode; + // Link this node to the previous node + prevNode.next = newNode; + + // Check if the previous node was the last node + if prevNode == tail { + this.tail = newNode; + } + } else { // No previous node was passed -> insert at head + newNode.next = this.head; + this.head = newNode; + } +} + +public p DoublyLinkedList.insertHead(T newValue) { + this.insert(newValue); +} + +public inline p DoublyLinkedList.insertTail(T newValue) { + this.insert(newValue, this.tail); +} + +/*public f*> DoublyLinkedList.find(T value) { + Node* currentNode = this.head; + while currentNode != nil*> { + // Check condition + if currentNode.value == value { + return currentNode; + } + // Move to next node + currentNode = currentNode.next; + } + return nil*>; +}*/ \ No newline at end of file diff --git a/std/data/linked-list.spice b/std/data/linked-list.spice new file mode 100644 index 000000000..1a3e9ab9e --- /dev/null +++ b/std/data/linked-list.spice @@ -0,0 +1,75 @@ +// Link external functions +ext malloc(long); +ext free(byte*); + +// Add generic type definitions +type T dyn; + +/** + * Node of a LinkedList + */ +public type Node struct { + T value + Node* next +} + +/** + * A linked list is a common, dynamically resizable data structure to store uniform data in order. + * It is characterized by the pointer for every item, pointing to the next one. + */ +public type LinkedList struct { + Node* head + Node* tail +} + +public p Node.dtor() { + if this.next != nil*> { + this.next.dtor(); + free((byte*) this.next); + } +} + +public p LinkedList.insert(T newValue, Node* prevNode = nil*>) { + // Create new node + Node* newNode; + unsafe { + newNode = (Node*) malloc(sizeof(type Node)); + } + newNode.value = newValue; + + if prevNode != nil*> { // Previous node was passed -> insert after this node + // Link the next node to this one + newNode.next = prevNode.next; + // Link this node to the previous node + prevNode.next = newNode; + + // Check if the previous node was the last node + if prevNode == tail { + this.tail = newNode; + } + } else { // No previous node was passed -> insert at head + newNode.next = this.head; + this.head = newNode; + } +} + +public p LinkedList.insertHead(T newValue) { + this.insert(newValue); +} + +public inline p LinkedList.insertTail(T newValue) { + this.insert(newValue, this.tail); +} + +/*public f*> LinkedList.find(T value) { + Node* currentNode = this.head; + while currentNode != nil*> { + // Check condition + if currentNode.value == value { + return currentNode; + } + // Move to next node + currentNode = currentNode.next; + } + return nil*>; +}*/ \ No newline at end of file From 19576330a1869fd5aecec487930fd9bd0e60a68f Mon Sep 17 00:00:00 2001 From: Marc Auberer Date: Thu, 15 Sep 2022 23:59:28 +0200 Subject: [PATCH 2/5] Prepare mechanism for runtime module import --- media/test-project/os-test.spice | 16 +++---- src/analyzer/AnalyzerVisitor.cpp | 9 ++-- src/analyzer/AnalyzerVisitor.h | 26 ++++++------ src/analyzer/PreAnalyzerVisitor.cpp | 11 +---- src/analyzer/PreAnalyzerVisitor.h | 3 +- src/cli/CliInterface.h | 7 --- src/dependency/SourceFile.cpp | 66 ++++++++++++++++++----------- src/dependency/SourceFile.h | 12 ++++-- src/linker/LinkerInterface.cpp | 8 +--- src/main.cpp | 15 ++++--- src/util/FileUtil.cpp | 30 +++++++++---- src/util/FileUtil.h | 1 + std/data/binary-tree.spice | 1 + test/TestUtil.cpp | 13 ++---- test/TestUtil.h | 8 ++-- 15 files changed, 120 insertions(+), 106 deletions(-) diff --git a/media/test-project/os-test.spice b/media/test-project/os-test.spice index ba3ee61af..06f765e3d 100644 --- a/media/test-project/os-test.spice +++ b/media/test-project/os-test.spice @@ -17,7 +17,7 @@ f main() { server.serve("/test", "Hello World!"); }*/ -/*import "std/runtime/string_rt" as _rt_str; +//import "std/runtime/string_rt" as _rt_str; f main() { //_rt_str::String s = _rt_str::String("Test"); @@ -34,12 +34,10 @@ f main() { string s3 = 2 * 'c' * 7; printf("Result: %s\n", s3); //printf("%s", s1 + s2); -}*/ - -//import "std/data/linked-list" as ll; +} -public f src(bool x, bool y) { - return 0 == ((x ? 1 : 8) & (y ? 1 : 8)); +/*public f src(bool x, bool y) { + return 0 == ((x ? 1 : 7) & (y ? 1 : 6)); } public f tgt(int x, int y) { @@ -48,8 +46,4 @@ public f tgt(int x, int y) { f main() { printf("Result: %d, %d", src(false, true), tgt(0, 1)); - - /*ll::LinkedList linkedList = ll::LinkedList(); - linkedList.insert(12s); - linkedList.insert(5s);*/ -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/analyzer/AnalyzerVisitor.cpp b/src/analyzer/AnalyzerVisitor.cpp index 2f8d374c0..85905040d 100644 --- a/src/analyzer/AnalyzerVisitor.cpp +++ b/src/analyzer/AnalyzerVisitor.cpp @@ -15,10 +15,9 @@ #include #include -AnalyzerVisitor::AnalyzerVisitor(const llvm::LLVMContext *context, const llvm::IRBuilder<> *builder, - const ThreadFactory &threadFactory, const SourceFile &sourceFile, CliOptions &options, - bool requiresMainFct, bool isStdFile) - : context(context), builder(builder), threadFactory(threadFactory), requiresMainFct(requiresMainFct), isStdFile(isStdFile) { +AnalyzerVisitor::AnalyzerVisitor(const llvm::LLVMContext *context, const llvm::IRBuilder<> *builder, const SourceFile &sourceFile, + CliOptions &options, RuntimeModules &runtimeModules, bool requiresMainFct, bool isStdFile) + : context(context), builder(builder), runtimeModules(runtimeModules), requiresMainFct(requiresMainFct), isStdFile(isStdFile) { // Retrieve symbol table this->currentScope = this->rootScope = sourceFile.symbolTable.get(); @@ -67,7 +66,7 @@ std::any AnalyzerVisitor::visitEntry(EntryNode *node) { } std::any AnalyzerVisitor::visitMainFctDef(MainFctDefNode *node) { - std::string mainSignature = MAIN_FUNCTION_NAME + "()"; + std::string mainSignature = std::string(MAIN_FUNCTION_NAME) + "()"; if (runNumber == 1) { // First run // Check if the function is already defined diff --git a/src/analyzer/AnalyzerVisitor.h b/src/analyzer/AnalyzerVisitor.h index c51ffa9ce..de3121027 100644 --- a/src/analyzer/AnalyzerVisitor.h +++ b/src/analyzer/AnalyzerVisitor.h @@ -13,15 +13,15 @@ #include #include -const std::string MAIN_FUNCTION_NAME = "main"; -const std::string RETURN_VARIABLE_NAME = "result"; -const std::string THIS_VARIABLE_NAME = "this"; -const std::string FOREACH_DEFAULT_IDX_VARIABLE_NAME = "idx"; -const std::string CTOR_VARIABLE_NAME = "ctor"; -const std::string DTOR_VARIABLE_NAME = "dtor"; -const std::string STRUCT_SCOPE_PREFIX = "struct:"; -const std::string ENUM_SCOPE_PREFIX = "enum:"; -const std::string UNUSED_VARIABLE_NAME = "_"; +const char *const MAIN_FUNCTION_NAME = "main"; +const char *const RETURN_VARIABLE_NAME = "result"; +const char *const THIS_VARIABLE_NAME = "this"; +const char *const FOREACH_DEFAULT_IDX_VARIABLE_NAME = "idx"; +const char *const CTOR_VARIABLE_NAME = "ctor"; +const char *const DTOR_VARIABLE_NAME = "dtor"; +const char *const STRUCT_SCOPE_PREFIX = "struct:"; +const char *const ENUM_SCOPE_PREFIX = "enum:"; +const char *const UNUSED_VARIABLE_NAME = "_"; const std::vector RESERVED_KEYWORDS = {"new", "switch", "case", "yield", "stash", "pick", "sync", "class"}; // Forward declarations @@ -32,6 +32,7 @@ class LinkerInterface; class SymbolTable; class SymbolTableEntry; class SourceFile; +struct RuntimeModules; /** * Visitor for analyzing a source file. @@ -42,12 +43,13 @@ class SourceFile; * - Type inference * - Type checking * - Resolve generic functions/procedure/structs + * - Detect usages of runtime modules */ class AnalyzerVisitor : public AstVisitor { public: // Constructors - explicit AnalyzerVisitor(const llvm::LLVMContext *context, const llvm::IRBuilder<> *builder, const ThreadFactory &threadFactory, - const SourceFile &sourceFile, CliOptions &options, bool requiresMainFct, bool stdFile); + explicit AnalyzerVisitor(const llvm::LLVMContext *context, const llvm::IRBuilder<> *builder, const SourceFile &sourceFile, + CliOptions &options, RuntimeModules &runtimeModules, bool requiresMainFct, bool stdFile); // Friend classes friend class OpRuleManager; @@ -111,7 +113,7 @@ class AnalyzerVisitor : public AstVisitor { const llvm::LLVMContext *context; const llvm::IRBuilder<> *builder; std::unique_ptr opRuleManager; - const ThreadFactory &threadFactory; + RuntimeModules &runtimeModules; bool requiresMainFct = true; bool hasMainFunction = false; bool isStdFile = false; diff --git a/src/analyzer/PreAnalyzerVisitor.cpp b/src/analyzer/PreAnalyzerVisitor.cpp index 9a4c84f25..f89796d75 100644 --- a/src/analyzer/PreAnalyzerVisitor.cpp +++ b/src/analyzer/PreAnalyzerVisitor.cpp @@ -28,17 +28,10 @@ std::any PreAnalyzerVisitor::visitImportStmt(ImportStmtNode *node) { if (node->importPath.rfind("std/", 0) == 0) { // Include source file from standard library std::string sourceFileIden = node->importPath.substr(node->importPath.find("std/") + 4); // Find std library - std::string stdPath; - if (FileUtil::fileExists("/usr/lib/spice/std")) { - stdPath = "/usr/lib/spice/std/"; - } else if (std::getenv("SPICE_STD_DIR") && FileUtil::dirExists(std::string(std::getenv("SPICE_STD_DIR")))) { - stdPath = std::string(std::getenv("SPICE_STD_DIR")); - if (stdPath.rfind(FileUtil::DIR_SEPARATOR) != stdPath.size() - 1) - stdPath += FileUtil::DIR_SEPARATOR; - } else { + std::string stdPath = FileUtil::getStdDir(); + if (stdPath.empty()) throw SemanticError(node->codeLoc, STD_NOT_FOUND, "Standard library could not be found. Check if the env var SPICE_STD_DIR exists"); - } // Check if source file exists std::string defaultPath = stdPath + sourceFileIden + ".spice"; std::string osPath = stdPath + sourceFileIden + "_" + cliOptions.targetOs + ".spice"; diff --git a/src/analyzer/PreAnalyzerVisitor.h b/src/analyzer/PreAnalyzerVisitor.h index aa2541463..95a0dccf0 100644 --- a/src/analyzer/PreAnalyzerVisitor.h +++ b/src/analyzer/PreAnalyzerVisitor.h @@ -17,7 +17,8 @@ class SourceFile; class PreAnalyzerVisitor : public AstVisitor { public: // Constructors - explicit PreAnalyzerVisitor(const CliOptions &options, SourceFile &sourceFile) : cliOptions(options), sourceFile(sourceFile) {} + explicit PreAnalyzerVisitor(const CliOptions &options, const SourceFile &sourceFiles) + : cliOptions(options), sourceFile(sourceFile) {} // Public methods std::any visitEntry(EntryNode *node) override; diff --git a/src/cli/CliInterface.h b/src/cli/CliInterface.h index 345023738..37e4e2589 100644 --- a/src/cli/CliInterface.h +++ b/src/cli/CliInterface.h @@ -6,12 +6,6 @@ #include "../../lib/cli11/CLI11.hpp" -#ifdef __unix__ -#define OS_UNIX -#elif defined(_WIN32) || defined(WIN32) -#define OS_WINDOWS -#endif - /** * Representation of the various cli options */ @@ -42,7 +36,6 @@ class CliInterface { public: // Constructors explicit CliInterface() = default; - explicit CliInterface(CliOptions options) : cliOptions(std::move(options)) {} // Public methods void createInterface(); diff --git a/src/dependency/SourceFile.cpp b/src/dependency/SourceFile.cpp index ee271ae41..c60999751 100644 --- a/src/dependency/SourceFile.cpp +++ b/src/dependency/SourceFile.cpp @@ -21,10 +21,10 @@ #include SourceFile::SourceFile(llvm::LLVMContext *context, llvm::IRBuilder<> *builder, ThreadFactory &threadFactory, - LinkerInterface &linker, CliOptions &options, SourceFile *parent, std::string name, - const std::string &filePath, bool stdFile) - : context(context), builder(builder), threadFactory(threadFactory), linker(linker), name(std::move(name)), filePath(filePath), - stdFile(stdFile), parent(parent), options(options) { + RuntimeModules &runtimeModules, LinkerInterface &linker, CliOptions &options, SourceFile *parent, + std::string name, const std::string &filePath, bool stdFile) + : context(context), builder(builder), threadFactory(threadFactory), runtimeModules(runtimeModules), linker(linker), + name(std::move(name)), filePath(filePath), stdFile(stdFile), parent(parent), options(options) { this->objectFilePath = options.outputDir + FileUtil::DIR_SEPARATOR + FileUtil::getFileName(filePath) + ".o"; // Deduce fileName and fileDir @@ -71,8 +71,8 @@ void SourceFile::visualizeCST() { dotCode += " label=\"" + replacedFilePath + "\";\n "; // Visualize the imported source files - for (const auto &[_, sourceFile] : dependencies) - sourceFile.first->visualizeCST(); + for (const auto &sourceFile : dependencies) + sourceFile.second.first->visualizeCST(); // Generate dot code for this source file CSTVisualizerVisitor visualizerVisitor(antlrCtx.lexer, antlrCtx.parser); @@ -106,8 +106,8 @@ void SourceFile::visualizeCST() { void SourceFile::buildAST() { // Transform the imported source files - for (const auto &[_, sourceFile] : dependencies) - sourceFile.first->buildAST(); + for (const auto &sourceFile : dependencies) + sourceFile.second.first->buildAST(); // Transform this source file AstBuilderVisitor astBuilder(ast.get(), filePath); @@ -126,8 +126,8 @@ void SourceFile::visualizeAST() { dotCode += " label=\"" + replacedFilePath + "\";\n "; // Visualize the imported source files - for (const auto &[_, sourceFile] : dependencies) - sourceFile.first->visualizeAST(); + for (const auto &sourceFile : dependencies) + sourceFile.second.first->visualizeAST(); // Generate dot code for this source file ASTVisualizerVisitor visualizerVisitor(ast.get()); @@ -165,9 +165,9 @@ void SourceFile::preAnalyze() { antlrCtx.parser->reset(); // Pre-analyze the imported source files - for (const auto &[_, sourceFile] : dependencies) { - sourceFile.first->buildAST(); - sourceFile.first->preAnalyze(); + for (const auto &sourceFile : dependencies) { + sourceFile.second.first->buildAST(); + sourceFile.second.first->preAnalyze(); } } @@ -188,9 +188,28 @@ void SourceFile::analyze() { } // Analyze this source file - analyzer = std::make_shared(context, builder, threadFactory, *this, options, parent == nullptr, stdFile); + analyzer = std::make_shared(context, builder, *this, options, runtimeModules, parent == nullptr, stdFile); analyzer->visit(ast.get()); antlrCtx.parser->reset(); + + // If this is the main source file, import the required runtime modules + if (parent != nullptr) { + std::string runtimePath = FileUtil::getStdDir() + FileUtil::DIR_SEPARATOR + "runtime" + FileUtil::DIR_SEPARATOR; + if (runtimeModules.stringRuntime) { + SourceFile stringRuntimeFile(context, builder, threadFactory, runtimeModules, linker, options, this, "__rt_string", + filePath, true); + stringRuntimeFile.preAnalyze(); + stringRuntimeFile.analyze(); + addDependency(ast.get(), "__rt_string", runtimePath + "string_rt.spice", true); + } + if (runtimeModules.threadRuntime) { + SourceFile stringRuntimeFile(context, builder, threadFactory, runtimeModules, linker, options, this, "__rt_thread", + filePath, true); + stringRuntimeFile.preAnalyze(); + stringRuntimeFile.analyze(); + addDependency(ast.get(), "__rt_thread", runtimePath + "thread_rt.spice", true); + } + } } void SourceFile::reAnalyze() { @@ -207,8 +226,8 @@ void SourceFile::reAnalyze() { } while (repetitionRequired); // Re-analyze the imported source files - for (const auto &[importName, sourceFile] : dependencies) - sourceFile.first->reAnalyze(); + for (const auto &sourceFile : dependencies) + sourceFile.second.first->reAnalyze(); // Save the JSON version in the compiler output compilerOutput.symbolTableString = symbolTable->toJSON().dump(2); @@ -257,8 +276,8 @@ void SourceFile::optimize() { return; // Optimize the imported source files - for (const auto &[_, sourceFile] : dependencies) - sourceFile.first->optimize(); + for (const auto &sourceFile : dependencies) + sourceFile.second.first->optimize(); generator->optimize(); @@ -275,8 +294,8 @@ void SourceFile::optimize() { void SourceFile::emitObjectFile() { // Optimize the imported source files - for (const auto &[_, sourceFile] : dependencies) - sourceFile.first->emitObjectFile(); + for (const auto &sourceFile : dependencies) + sourceFile.second.first->emitObjectFile(); // Dump assembly code if (options.dumpAssembly) { // GCOV_EXCL_START @@ -302,10 +321,9 @@ void SourceFile::addDependency(const AstNode *declAstNode, const std::string &na throw SemanticError(declAstNode->codeLoc, CIRCULAR_DEPENDENCY, "Circular import detected while importing '" + filePath + "'"); // Add the dependency - dependencies.insert( - {name, - {std::make_shared(context, builder, threadFactory, linker, options, this, name, filePath, stdFile), - declAstNode}}); + auto sourceFile = std::make_shared(context, builder, threadFactory, runtimeModules, linker, options, this, name, + filePath, stdFile); + dependencies.insert({name, {sourceFile, declAstNode}}); } bool SourceFile::isAlreadyImported(const std::string &filePathSearch) const { diff --git a/src/dependency/SourceFile.h b/src/dependency/SourceFile.h index 4b3f0204f..804787eff 100644 --- a/src/dependency/SourceFile.h +++ b/src/dependency/SourceFile.h @@ -17,7 +17,6 @@ class AnalyzerVisitor; class GeneratorVisitor; class AntlrThrowingErrorListener; class SymbolTable; -class ErrorFactory; struct CliOptions; class LinkerInterface; class ThreadFactory; @@ -42,12 +41,18 @@ struct CompilerOutput { std::string irOptString; }; +// Structs +struct RuntimeModules { + bool stringRuntime = false; + bool threadRuntime = false; +}; + class SourceFile { public: // Constructors explicit SourceFile(llvm::LLVMContext *context, llvm::IRBuilder<> *builder, ThreadFactory &threadFactory, - LinkerInterface &linker, CliOptions &options, SourceFile *parent, std::string name, - const std::string &filePath, bool stdFile); + RuntimeModules &runtimeModules, LinkerInterface &linker, CliOptions &options, SourceFile *parent, + std::string name, const std::string &filePath, bool stdFile); // Public methods void visualizeCST(); @@ -85,4 +90,5 @@ class SourceFile { llvm::IRBuilder<> *builder; ThreadFactory &threadFactory; LinkerInterface &linker; + RuntimeModules &runtimeModules; }; \ No newline at end of file diff --git a/src/linker/LinkerInterface.cpp b/src/linker/LinkerInterface.cpp index b18bc4318..74de24030 100644 --- a/src/linker/LinkerInterface.cpp +++ b/src/linker/LinkerInterface.cpp @@ -9,12 +9,6 @@ #include #include -#ifdef __unix__ -#define OS_UNIX -#elif defined(_WIN32) || defined(WIN32) -#define OS_WINDOWS -#endif - const char *LINKER_EXECUTABLE_NAME = "gcc"; /** @@ -23,7 +17,7 @@ const char *LINKER_EXECUTABLE_NAME = "gcc"; void LinkerInterface::link() { if (FileUtil::isCommandAvailable(std::string(LINKER_EXECUTABLE_NAME))) // GCOV_EXCL_START throw LinkerError(LINKER_NOT_FOUND, "Please check if you have installed " + std::string(LINKER_EXECUTABLE_NAME) + - " and added it to the PATH variable"); // GCOV_EXCL_STOP + " and added it to the PATH variable"); // GCOV_EXCL_STOP // Check if the output path was set if (outputPath.empty()) diff --git a/src/main.cpp b/src/main.cpp index 8df73bbc2..dba659b40 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,11 @@ // Copyright (c) 2021-2022 ChilliBits. All rights reserved. +#ifdef __unix__ +#define OS_UNIX +#elif defined(_WIN32) || defined(WIN32) +#define OS_WINDOWS +#endif + #include #include #include @@ -21,15 +27,14 @@ bool compileProject(CliOptions &options) { llvm::LLVMContext context; llvm::IRBuilder<> builder(context); - // Prepare instance of thread factory, which has to exist exactly once per executable + // Prepare global Spice assets ThreadFactory threadFactory = ThreadFactory(); - - // Prepare linker interface LinkerInterface linker = LinkerInterface(threadFactory, options); + RuntimeModules runtimeModules = {false, false}; // Create source file instance for main source file - SourceFile mainSourceFile = - SourceFile(&context, &builder, threadFactory, linker, options, nullptr, "root", options.mainSourceFile, false); + SourceFile mainSourceFile(&context, &builder, threadFactory, runtimeModules, linker, options, nullptr, "root", + options.mainSourceFile, false); // Visualize the parse tree (only runs in debug mode) mainSourceFile.visualizeCST(); diff --git a/src/util/FileUtil.cpp b/src/util/FileUtil.cpp index e4aa3d6a7..a9ddb359a 100644 --- a/src/util/FileUtil.cpp +++ b/src/util/FileUtil.cpp @@ -7,12 +7,6 @@ #include #include -#ifdef __unix__ -#define OS_UNIX -#elif defined(_WIN32) || defined(WIN32) -#define OS_WINDOWS -#endif - /** * Checks if a certain file exists on the file system * @@ -97,7 +91,7 @@ ExecResult FileUtil::exec(const std::string &cmd) { result += buffer; } int exitCode = pclose(pipe) / 256; - return { result, exitCode }; + return {result, exitCode}; } /** @@ -114,13 +108,33 @@ bool FileUtil::isCommandAvailable(const std::string &cmd) { return std::system(checkCmd.c_str()); } +/** + * Retrieve the dir, where the standard library lives. + * Returns an empty string if the std was not found. + * + * @return Std directory + */ +std::string FileUtil::getStdDir() { +#ifndef OS_WINDOWS + if (FileUtil::fileExists("/usr/lib/spice/std")) + return "/usr/lib/spice/std/"; +#endif + if (std::getenv("SPICE_STD_DIR") && FileUtil::dirExists(std::string(std::getenv("SPICE_STD_DIR")))) { + std::string stdPath = std::string(std::getenv("SPICE_STD_DIR")); + if (stdPath.rfind(FileUtil::DIR_SEPARATOR) != stdPath.size() - 1) + stdPath += FileUtil::DIR_SEPARATOR; + return stdPath; + } + return ""; +} + /** * Retrieve the dir, where output binaries should go when installing them * * @return Installation directory */ std::string FileUtil::getSpiceBinDir() { -#ifdef _WIN32 +#ifdef OS_WINDOWS return std::string(std::getenv("USERPROFILE")) + R"(\spice\bin\)"; #else return "/usr/local/bin/"; diff --git a/src/util/FileUtil.h b/src/util/FileUtil.h index cd55603cb..ee558b589 100644 --- a/src/util/FileUtil.h +++ b/src/util/FileUtil.h @@ -29,5 +29,6 @@ class FileUtil { static std::string getFileDir(const std::string &filePath); static ExecResult exec(const std::string &cmd); static bool isCommandAvailable(const std::string &cmd); + static std::string getStdDir(); static std::string getSpiceBinDir(); }; \ No newline at end of file diff --git a/std/data/binary-tree.spice b/std/data/binary-tree.spice index 869266ab2..4f44a2b91 100644 --- a/std/data/binary-tree.spice +++ b/std/data/binary-tree.spice @@ -48,4 +48,5 @@ public p Node.dtor() { public p BinaryTree.insert(T newValue, Node* baseNode = nil*>) { // Search position where to insert + // ToDo } \ No newline at end of file diff --git a/test/TestUtil.cpp b/test/TestUtil.cpp index 7e8c98b7a..c29d169f6 100644 --- a/test/TestUtil.cpp +++ b/test/TestUtil.cpp @@ -2,24 +2,19 @@ // GCOV_EXCL_START -#ifdef __unix__ -#define OS_UNIX -#elif defined(_WIN32) || defined(WIN32) -#define OS_WINDOWS -#endif - #include "TestUtil.h" #include #include -#ifdef OS_UNIX -#include // Required by builds on Linux -#endif #include #include +#ifdef OS_UNIX +#include // Required by builds on Linux +#endif + /** * Collect the test cases in a particular test suite * diff --git a/test/TestUtil.h b/test/TestUtil.h index ce09560fa..e389b6000 100644 --- a/test/TestUtil.h +++ b/test/TestUtil.h @@ -12,12 +12,10 @@ #include -#ifdef __unix__ -#define OS_UNIX -const char *const PATH_TEST_FILES = "./test-files/"; -#elif defined(_WIN32) || defined(WIN32) -#define OS_WINDOWS +#ifdef OS_WINDOWS const char *const PATH_TEST_FILES = ".\\test-files\\"; +#else +const char *const PATH_TEST_FILES = "./test-files/"; #endif const unsigned int EXPECTED_NUMBER_OF_TESTS = 250; const unsigned int IR_FILE_SKIP_LINES = 4; // Skip the first couple of lines, because they contain target dependent information From bcc4e47dcb4259d75c8bde47837e7c39576df222 Mon Sep 17 00:00:00 2001 From: Marc Auberer Date: Sat, 17 Sep 2022 12:48:14 +0200 Subject: [PATCH 3/5] Fix bug --- .github/workflows/publish.yml | 2 +- Options.cmake | 9 ++++++++- media/test-project/os-test.spice | 10 +++++----- src/analyzer/PreAnalyzerVisitor.h | 3 +-- src/cli/CliInterface.cpp | 6 +++--- src/main.cpp | 6 ------ src/util/FileUtil.cpp | 9 +++++---- test/TestRunner.cpp | 5 +++-- test/TestUtil.cpp | 2 +- test/TestUtil.h | 2 +- 10 files changed, 28 insertions(+), 26 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2dde56d4f..8909fa92d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -222,7 +222,7 @@ jobs: - name: Run GoReleaser uses: goreleaser/goreleaser-action@v3 with: - version: v1.11.2 + version: v1.11.3 args: release --rm-dist env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/Options.cmake b/Options.cmake index c69b648c2..4afa40e4a 100644 --- a/Options.cmake +++ b/Options.cmake @@ -55,4 +55,11 @@ if (SPICE_IS_GH_ACTIONS) ADD_DEFINITIONS(-DSPICE_IS_GH_ACTIONS) else() message(STATUS "Spice: Running all the tests.") -endif() \ No newline at end of file +endif() + +# Add additional definitions +IF (WIN32) + ADD_DEFINITIONS(-DOS_WINDOWS) +ELSE() + ADD_DEFINITIONS(-DOS_UNIX) +ENDIF() \ No newline at end of file diff --git a/media/test-project/os-test.spice b/media/test-project/os-test.spice index 06f765e3d..44795bef9 100644 --- a/media/test-project/os-test.spice +++ b/media/test-project/os-test.spice @@ -19,7 +19,7 @@ f main() { //import "std/runtime/string_rt" as _rt_str; -f main() { +/*f main() { //_rt_str::String s = _rt_str::String("Test"); //printf("%s", s.getRaw()); // Plus @@ -34,10 +34,10 @@ f main() { string s3 = 2 * 'c' * 7; printf("Result: %s\n", s3); //printf("%s", s1 + s2); -} +}*/ -/*public f src(bool x, bool y) { - return 0 == ((x ? 1 : 7) & (y ? 1 : 6)); +public f src(bool x, bool y) { + return ((x ? 1 : 4) & (y ? 1 : 4)) == 0; } public f tgt(int x, int y) { @@ -46,4 +46,4 @@ public f tgt(int x, int y) { f main() { printf("Result: %d, %d", src(false, true), tgt(0, 1)); -}*/ \ No newline at end of file +} \ No newline at end of file diff --git a/src/analyzer/PreAnalyzerVisitor.h b/src/analyzer/PreAnalyzerVisitor.h index 95a0dccf0..aa2541463 100644 --- a/src/analyzer/PreAnalyzerVisitor.h +++ b/src/analyzer/PreAnalyzerVisitor.h @@ -17,8 +17,7 @@ class SourceFile; class PreAnalyzerVisitor : public AstVisitor { public: // Constructors - explicit PreAnalyzerVisitor(const CliOptions &options, const SourceFile &sourceFiles) - : cliOptions(options), sourceFile(sourceFile) {} + explicit PreAnalyzerVisitor(const CliOptions &options, SourceFile &sourceFile) : cliOptions(options), sourceFile(sourceFile) {} // Public methods std::any visitEntry(EntryNode *node) override; diff --git a/src/cli/CliInterface.cpp b/src/cli/CliInterface.cpp index fb99d66ab..7a6c751be 100644 --- a/src/cli/CliInterface.cpp +++ b/src/cli/CliInterface.cpp @@ -37,7 +37,7 @@ void CliInterface::createInterface() { std::string installPath = FileUtil::getSpiceBinDir(); FileUtil::createDirs(installPath); installPath += FileUtil::getFileName(cliOptions.mainSourceFile.substr(0, cliOptions.mainSourceFile.length() - 6)); -#ifdef OS_WINDOWS +#if OS_WINDOWS installPath += ".exe"; #endif cliOptions.outputPath = installPath; @@ -48,7 +48,7 @@ void CliInterface::createInterface() { cliOptions.outputPath = "."; if (cliOptions.outputPath == "." || cliOptions.outputPath == "..") { cliOptions.outputPath = FileUtil::getFileName(cliOptions.mainSourceFile.substr(0, cliOptions.mainSourceFile.length() - 6)); -#ifdef OS_WINDOWS +#if OS_WINDOWS cliOptions.outputPath += ".exe"; #endif } @@ -307,7 +307,7 @@ void CliInterface::addUninstallSubcommand() { subCmd->callback([&]() { std::string installPath = FileUtil::getSpiceBinDir(); installPath += FileUtil::getFileName(cliOptions.mainSourceFile.substr(0, cliOptions.mainSourceFile.length() - 6)); -#ifdef OS_WINDOWS +#if OS_WINDOWS installPath += ".exe"; #endif if (!FileUtil::fileExists(installPath)) { diff --git a/src/main.cpp b/src/main.cpp index dba659b40..8b544b5d7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,11 +1,5 @@ // Copyright (c) 2021-2022 ChilliBits. All rights reserved. -#ifdef __unix__ -#define OS_UNIX -#elif defined(_WIN32) || defined(WIN32) -#define OS_WINDOWS -#endif - #include #include #include diff --git a/src/util/FileUtil.cpp b/src/util/FileUtil.cpp index a9ddb359a..b66ece9ca 100644 --- a/src/util/FileUtil.cpp +++ b/src/util/FileUtil.cpp @@ -101,9 +101,10 @@ ExecResult FileUtil::exec(const std::string &cmd) { * @return Present or not */ bool FileUtil::isCommandAvailable(const std::string &cmd) { +#if OS_WINDOWS + std::string checkCmd = "where " + cmd + " > nul 2>&1"; +#else std::string checkCmd = "which " + cmd + " > /dev/null 2>&1"; -#ifdef OS_WINDOWS - checkCmd = "where " + cmd + " > nul 2>&1"; #endif return std::system(checkCmd.c_str()); } @@ -115,7 +116,7 @@ bool FileUtil::isCommandAvailable(const std::string &cmd) { * @return Std directory */ std::string FileUtil::getStdDir() { -#ifndef OS_WINDOWS +#ifdef OS_UNIX if (FileUtil::fileExists("/usr/lib/spice/std")) return "/usr/lib/spice/std/"; #endif @@ -134,7 +135,7 @@ std::string FileUtil::getStdDir() { * @return Installation directory */ std::string FileUtil::getSpiceBinDir() { -#ifdef OS_WINDOWS +#if OS_WINDOWS return std::string(std::getenv("USERPROFILE")) + R"(\spice\bin\)"; #else return "/usr/local/bin/"; diff --git a/test/TestRunner.cpp b/test/TestRunner.cpp index 28d4c1f0b..964abef1c 100644 --- a/test/TestRunner.cpp +++ b/test/TestRunner.cpp @@ -51,11 +51,12 @@ void execTestCase(const TestCase &testCase) { llvm::IRBuilder<> builder(context); ThreadFactory threadFactory = ThreadFactory(); LinkerInterface linker = LinkerInterface(threadFactory, options); + RuntimeModules runtimeModules = {false, false}; try { // Create source file instance for main source file - SourceFile mainSourceFile = - SourceFile(&context, &builder, threadFactory, linker, options, nullptr, "root", options.mainSourceFile, false); + SourceFile mainSourceFile = SourceFile(&context, &builder, threadFactory, runtimeModules, linker, options, nullptr, "root", + options.mainSourceFile, false); // Check CST TestUtil::checkRefMatch(testCase.testPath + FileUtil::DIR_SEPARATOR + REF_NAME_PARSE_TREE, [&]() { diff --git a/test/TestUtil.cpp b/test/TestUtil.cpp index c29d169f6..d3b89a3ee 100644 --- a/test/TestUtil.cpp +++ b/test/TestUtil.cpp @@ -137,7 +137,7 @@ std::string TestUtil::toCamelCase(std::string input) { */ std::string TestUtil::getDefaultExecutableName() { std::string executableName = "./source"; -#ifdef OS_WINDOWS +#if OS_WINDOWS executableName = ".\\source.exe"; #endif return executableName; diff --git a/test/TestUtil.h b/test/TestUtil.h index e389b6000..347edf4ff 100644 --- a/test/TestUtil.h +++ b/test/TestUtil.h @@ -12,7 +12,7 @@ #include -#ifdef OS_WINDOWS +#if OS_WINDOWS const char *const PATH_TEST_FILES = ".\\test-files\\"; #else const char *const PATH_TEST_FILES = "./test-files/"; From c32a73824b79e78c3524489a97588adc28f3aab0 Mon Sep 17 00:00:00 2001 From: Marc Auberer Date: Sat, 17 Sep 2022 17:02:51 +0200 Subject: [PATCH 4/5] Fix bug --- .run/Spice_run.run.xml | 2 +- media/test-project/os-test.spice | 10 ++--- src/analyzer/AnalyzerVisitor.cpp | 5 +++ src/ast/AstNodes.h | 4 +- src/dependency/SourceFile.cpp | 42 +++++++++---------- src/generator/GeneratorVisitor.cpp | 4 +- src/linker/LinkerInterface.cpp | 2 +- src/symbol/SymbolTable.cpp | 2 +- src/util/FileUtil.cpp | 4 +- .../string-basic-operations/source.spice | 2 - .../runtime/string-operators/ir-code-O2.ll | 4 +- .../std/runtime/string-operators/source.spice | 2 - 12 files changed, 41 insertions(+), 42 deletions(-) diff --git a/.run/Spice_run.run.xml b/.run/Spice_run.run.xml index 77c4d605a..67ebee1e4 100644 --- a/.run/Spice_run.run.xml +++ b/.run/Spice_run.run.xml @@ -1,5 +1,5 @@ - + diff --git a/media/test-project/os-test.spice b/media/test-project/os-test.spice index 44795bef9..0f1af5b7b 100644 --- a/media/test-project/os-test.spice +++ b/media/test-project/os-test.spice @@ -19,9 +19,7 @@ f main() { //import "std/runtime/string_rt" as _rt_str; -/*f main() { - //_rt_str::String s = _rt_str::String("Test"); - //printf("%s", s.getRaw()); +f main() { // Plus printf("Result: %s\n", "Hello " + "World!"); string s1 = "Hello " + "World!"; @@ -34,9 +32,9 @@ f main() { string s3 = 2 * 'c' * 7; printf("Result: %s\n", s3); //printf("%s", s1 + s2); -}*/ +} -public f src(bool x, bool y) { +/*public f src(bool x, bool y) { return ((x ? 1 : 4) & (y ? 1 : 4)) == 0; } @@ -46,4 +44,4 @@ public f tgt(int x, int y) { f main() { printf("Result: %d, %d", src(false, true), tgt(0, 1)); -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/analyzer/AnalyzerVisitor.cpp b/src/analyzer/AnalyzerVisitor.cpp index 85905040d..2af5aa7be 100644 --- a/src/analyzer/AnalyzerVisitor.cpp +++ b/src/analyzer/AnalyzerVisitor.cpp @@ -2304,8 +2304,13 @@ std::any AnalyzerVisitor::visitCustomDataType(CustomDataTypeNode *node) { } SymbolType AnalyzerVisitor::insertAnonStringStructSymbol(const AstNode *declNode) { + // Insert anonymous string symbol SymbolType stringStructType(TY_STRING, "", {.isStringStruct = true}, {}); currentScope->insertAnonymous(stringStructType, declNode); + + // Enable string runtime + runtimeModules.stringRuntime = true; + return stringStructType; } diff --git a/src/ast/AstNodes.h b/src/ast/AstNodes.h index 70d6e9192..738ab6e9a 100644 --- a/src/ast/AstNodes.h +++ b/src/ast/AstNodes.h @@ -83,8 +83,6 @@ class AstNode { SymbolType setEvaluatedSymbolType(const SymbolType &symbolType) { size_t index = getSymbolTypeIndex(); - // if (symbolTypes.capacity() <= index) - // symbolTypes.reserve(index + 1); symbolTypes.insert(symbolTypes.begin() + index, symbolType); return symbolType; } @@ -126,7 +124,7 @@ class AstNode { const CodeLoc codeLoc; size_t symbolTypeIndex = SIZE_MAX; std::vector symbolTypes; - CompileTimeValue compileTimeValue; + CompileTimeValue compileTimeValue = {}; std::string compileTimeStringValue; bool hasDirectCompileTimeValue = false; }; diff --git a/src/dependency/SourceFile.cpp b/src/dependency/SourceFile.cpp index c60999751..2a36c33a7 100644 --- a/src/dependency/SourceFile.cpp +++ b/src/dependency/SourceFile.cpp @@ -191,25 +191,6 @@ void SourceFile::analyze() { analyzer = std::make_shared(context, builder, *this, options, runtimeModules, parent == nullptr, stdFile); analyzer->visit(ast.get()); antlrCtx.parser->reset(); - - // If this is the main source file, import the required runtime modules - if (parent != nullptr) { - std::string runtimePath = FileUtil::getStdDir() + FileUtil::DIR_SEPARATOR + "runtime" + FileUtil::DIR_SEPARATOR; - if (runtimeModules.stringRuntime) { - SourceFile stringRuntimeFile(context, builder, threadFactory, runtimeModules, linker, options, this, "__rt_string", - filePath, true); - stringRuntimeFile.preAnalyze(); - stringRuntimeFile.analyze(); - addDependency(ast.get(), "__rt_string", runtimePath + "string_rt.spice", true); - } - if (runtimeModules.threadRuntime) { - SourceFile stringRuntimeFile(context, builder, threadFactory, runtimeModules, linker, options, this, "__rt_thread", - filePath, true); - stringRuntimeFile.preAnalyze(); - stringRuntimeFile.analyze(); - addDependency(ast.get(), "__rt_thread", runtimePath + "thread_rt.spice", true); - } - } } void SourceFile::reAnalyze() { @@ -229,6 +210,25 @@ void SourceFile::reAnalyze() { for (const auto &sourceFile : dependencies) sourceFile.second.first->reAnalyze(); + // If this is the main source file, import the required runtime modules + if (parent == nullptr) { + std::vector> runtimeFiles; + if (runtimeModules.stringRuntime) + runtimeFiles.emplace_back("__rt_string", "string_rt"); + if (runtimeModules.threadRuntime) + runtimeFiles.emplace_back("__rt_thread", "thread_rt"); + + std::string runtimePath = FileUtil::getStdDir() + "runtime" + FileUtil::DIR_SEPARATOR; + for (const auto &[importName, fileName] : runtimeFiles) { + addDependency(ast.get(), importName, runtimePath + fileName + ".spice", true); + auto &[stringRuntimeFile, _] = dependencies.at(importName); + stringRuntimeFile->buildAST(); + stringRuntimeFile->preAnalyze(); + stringRuntimeFile->analyze(); + stringRuntimeFile->reAnalyze(); + } + } + // Save the JSON version in the compiler output compilerOutput.symbolTableString = symbolTable->toJSON().dump(2); @@ -241,8 +241,8 @@ void SourceFile::reAnalyze() { void SourceFile::generate() { // Generate the imported source files - for (const auto &[_, sourceFile] : dependencies) - sourceFile.first->generate(); + for (const auto &sourceFile : dependencies) + sourceFile.second.first->generate(); // Generate this source file generator = std::make_shared(context, builder, threadFactory, linker, options, *this, objectFilePath); diff --git a/src/generator/GeneratorVisitor.cpp b/src/generator/GeneratorVisitor.cpp index d90170d3f..8f50721ba 100644 --- a/src/generator/GeneratorVisitor.cpp +++ b/src/generator/GeneratorVisitor.cpp @@ -351,7 +351,7 @@ std::any GeneratorVisitor::visitFctDef(FctDefNode *node) { spiceFunc.getThisType().getBaseType().getTemplateTypes()); // Get the LLVM type of the struct symbol SymbolType thisSymbolType = spiceFunc.getThisType(); - argNames.push_back(THIS_VARIABLE_NAME); + argNames.emplace_back(THIS_VARIABLE_NAME); llvm::Type *thisType = thisSymbolType.toLLVMType(*context, accessScope)->getPointerTo(); argTypes.push_back(thisType); // Change scope to struct @@ -547,7 +547,7 @@ std::any GeneratorVisitor::visitProcDef(ProcDefNode *node) { std::string structSignature = Struct::getSignature(spiceProc.getThisType().getBaseType().getSubType(), spiceProc.getThisType().getBaseType().getTemplateTypes()); // Get the LLVM type of the struct symbol - argNames.push_back(THIS_VARIABLE_NAME); + argNames.emplace_back(THIS_VARIABLE_NAME); llvm::Type *thisType = spiceProc.getThisType().toLLVMType(*context, accessScope)->getPointerTo(); argTypes.push_back(thisType); // Change scope to struct diff --git a/src/linker/LinkerInterface.cpp b/src/linker/LinkerInterface.cpp index 74de24030..61de7f3a7 100644 --- a/src/linker/LinkerInterface.cpp +++ b/src/linker/LinkerInterface.cpp @@ -9,7 +9,7 @@ #include #include -const char *LINKER_EXECUTABLE_NAME = "gcc"; +const char *const LINKER_EXECUTABLE_NAME = "gcc"; /** * Start the linking process diff --git a/src/symbol/SymbolTable.cpp b/src/symbol/SymbolTable.cpp index 0c9235423..d1c0c1e4f 100644 --- a/src/symbol/SymbolTable.cpp +++ b/src/symbol/SymbolTable.cpp @@ -866,4 +866,4 @@ nlohmann::json SymbolTable::toJSON() const { result["captures"] = jsonCaptures; result["children"] = jsonChildren; return result; -} +} \ No newline at end of file diff --git a/src/util/FileUtil.cpp b/src/util/FileUtil.cpp index b66ece9ca..41ada0704 100644 --- a/src/util/FileUtil.cpp +++ b/src/util/FileUtil.cpp @@ -3,10 +3,11 @@ #include "FileUtil.h" #include -#include #include #include +#include + /** * Checks if a certain file exists on the file system * @@ -122,6 +123,7 @@ std::string FileUtil::getStdDir() { #endif if (std::getenv("SPICE_STD_DIR") && FileUtil::dirExists(std::string(std::getenv("SPICE_STD_DIR")))) { std::string stdPath = std::string(std::getenv("SPICE_STD_DIR")); + CommonUtil::replaceAll(stdPath, "/", "\\"); if (stdPath.rfind(FileUtil::DIR_SEPARATOR) != stdPath.size() - 1) stdPath += FileUtil::DIR_SEPARATOR; return stdPath; diff --git a/test/test-files/std/runtime/string-basic-operations/source.spice b/test/test-files/std/runtime/string-basic-operations/source.spice index 026af58f9..4a1d45039 100644 --- a/test/test-files/std/runtime/string-basic-operations/source.spice +++ b/test/test-files/std/runtime/string-basic-operations/source.spice @@ -1,5 +1,3 @@ -import "std/runtime/string_rt" as _rt_str; - f main() { _rt_str::String s = _rt_str::String("Hello "); printf("Content: %s\n", s.getRaw()); diff --git a/test/test-files/std/runtime/string-operators/ir-code-O2.ll b/test/test-files/std/runtime/string-operators/ir-code-O2.ll index 8c78a849c..c15ba551c 100644 --- a/test/test-files/std/runtime/string-operators/ir-code-O2.ll +++ b/test/test-files/std/runtime/string-operators/ir-code-O2.ll @@ -18,7 +18,7 @@ target triple = "x86_64-w64-windows-gnu" @10 = private unnamed_addr constant [12 x i8] c"Result: %s\0A\00", align 1 define i32 @main() local_unnamed_addr { -entry.l3: +entry.l1: %0 = alloca %_s__String__charptr_long_long, align 8 %1 = alloca %_s__String__charptr_long_long, align 8 %2 = alloca %_s__String__charptr_long_long, align 8 @@ -91,7 +91,6 @@ entry.l3: call void @_mp__String__opMul__int(ptr nonnull %10, i32 3) %33 = call ptr @_mf__String__getRaw(ptr nonnull %10) %34 = call i32 (ptr, ...) @printf(ptr nonnull @10, ptr %33) - call void @_mp__String__dtor(ptr nonnull %5) call void @_mp__String__dtor(ptr nonnull %6) call void @_mp__String__dtor(ptr nonnull %7) call void @_mp__String__dtor(ptr nonnull %8) @@ -100,6 +99,7 @@ entry.l3: call void @_mp__String__dtor(ptr nonnull %0) call void @_mp__String__dtor(ptr nonnull %2) call void @_mp__String__dtor(ptr nonnull %4) + call void @_mp__String__dtor(ptr nonnull %5) ret i32 0 } diff --git a/test/test-files/std/runtime/string-operators/source.spice b/test/test-files/std/runtime/string-operators/source.spice index 0cfed9962..b1909bbf0 100644 --- a/test/test-files/std/runtime/string-operators/source.spice +++ b/test/test-files/std/runtime/string-operators/source.spice @@ -1,5 +1,3 @@ -import "std/runtime/string_rt" as _rt_str; - f main() { // Plus printf("Result: %s\n", "Hello " + "World!"); From 5d53e5703c14ac6399a8813ec6ee68c7dea45a20 Mon Sep 17 00:00:00 2001 From: Marc Auberer Date: Sat, 17 Sep 2022 21:16:21 +0200 Subject: [PATCH 5/5] Fix CI bug --- media/test-project/os-test.spice | 21 ++------------------- src/util/FileUtil.cpp | 2 ++ 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/media/test-project/os-test.spice b/media/test-project/os-test.spice index 0f1af5b7b..f0f5d46e2 100644 --- a/media/test-project/os-test.spice +++ b/media/test-project/os-test.spice @@ -1,4 +1,4 @@ -/*import "std/data/vector" as vec; +import "std/data/vector" as vec; import "std/data/pair" as pair; f main() { @@ -8,7 +8,7 @@ f main() { pair::Pair p1 = pairVector.get(1); printf("Hello %s!", p1.getSecond()); -}*/ +} /*import "std/net/http" as http; @@ -17,23 +17,6 @@ f main() { server.serve("/test", "Hello World!"); }*/ -//import "std/runtime/string_rt" as _rt_str; - -f main() { - // Plus - printf("Result: %s\n", "Hello " + "World!"); - string s1 = "Hello " + "World!"; - printf("Result: %s\n", s1); - // Mul - printf("Result: %s\n", 4s * "Hi"); - string s2 = "Hello " * 5; - printf("Result: %s\n", s2); - printf("Result: %s\n", 20 * 'a'); - string s3 = 2 * 'c' * 7; - printf("Result: %s\n", s3); - //printf("%s", s1 + s2); -} - /*public f src(bool x, bool y) { return ((x ? 1 : 4) & (y ? 1 : 4)) == 0; } diff --git a/src/util/FileUtil.cpp b/src/util/FileUtil.cpp index 41ada0704..cf806f61a 100644 --- a/src/util/FileUtil.cpp +++ b/src/util/FileUtil.cpp @@ -123,7 +123,9 @@ std::string FileUtil::getStdDir() { #endif if (std::getenv("SPICE_STD_DIR") && FileUtil::dirExists(std::string(std::getenv("SPICE_STD_DIR")))) { std::string stdPath = std::string(std::getenv("SPICE_STD_DIR")); +#ifdef OS_WINDOWS CommonUtil::replaceAll(stdPath, "/", "\\"); +#endif if (stdPath.rfind(FileUtil::DIR_SEPARATOR) != stdPath.size() - 1) stdPath += FileUtil::DIR_SEPARATOR; return stdPath;