From c6eaa302ffd731aa98f5b4746717d09fe2349f48 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 13:29:48 +0200 Subject: [PATCH 01/28] Bumped --- d | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 d diff --git a/d b/d new file mode 100644 index 000000000..e69de29bb From 2cb02d3ad2b6b27b5f0c1a1fe567c6eac2cdea8e Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 13:29:54 +0200 Subject: [PATCH 02/28] Bumped (removed) --- d | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 d diff --git a/d b/d deleted file mode 100644 index e69de29bb..000000000 From 0fd9d8de8ff72a5dbd53f8980a749a226650db35 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 13:55:04 +0200 Subject: [PATCH 03/28] Check - Added forward and reverse mapping for new `SymbolType.IMPORT `symbol --- source/tlang/compiler/symbols/check.d | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source/tlang/compiler/symbols/check.d b/source/tlang/compiler/symbols/check.d index 9cd8c8495..7eabc3183 100644 --- a/source/tlang/compiler/symbols/check.d +++ b/source/tlang/compiler/symbols/check.d @@ -290,6 +290,11 @@ public enum SymbolType */ GENERIC_TYPE_DECLARE, + /** + * `import` keyword + */ + IMPORT, + /** * Unknown symbol */ @@ -695,6 +700,11 @@ public SymbolType getSymbolType(Token tokenIn) { return SymbolType.GENERIC_TYPE_DECLARE; } + /* import keyword */ + else if(cmp(token, "import") == 0) + { + return SymbolType.IMPORT; + } /* An identifier/type (of some sorts) - further inspection in parser is needed */ else if(isPathIdentifier(token) || isIdentifier(token)) { From fa6265f5b15283e042ac035bccc6127e3e786f21 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 13:59:40 +0200 Subject: [PATCH 04/28] Data - Removed that, idk what that was lmao --- source/tlang/compiler/symbols/data.d | 1 - 1 file changed, 1 deletion(-) diff --git a/source/tlang/compiler/symbols/data.d b/source/tlang/compiler/symbols/data.d index 6f7acef83..3a55cbcc5 100644 --- a/source/tlang/compiler/symbols/data.d +++ b/source/tlang/compiler/symbols/data.d @@ -22,7 +22,6 @@ import tlang.compiler.symbols.mcro : MStatementSearchable, MStatementReplaceable public class Program { private string moduleName; - private Program[] importedModules; private Statement[] statements; From 7c7cfcbfc3d1adf3eea2a038357a9e54ead2eae4 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 14:00:48 +0200 Subject: [PATCH 05/28] Data - Made `Program` empty - starting from the beginning again now --- source/tlang/compiler/symbols/data.d | 62 +--------------------------- 1 file changed, 1 insertion(+), 61 deletions(-) diff --git a/source/tlang/compiler/symbols/data.d b/source/tlang/compiler/symbols/data.d index 3a55cbcc5..42ccb3ff8 100644 --- a/source/tlang/compiler/symbols/data.d +++ b/source/tlang/compiler/symbols/data.d @@ -21,67 +21,7 @@ import tlang.compiler.symbols.mcro : MStatementSearchable, MStatementReplaceable public class Program { - private string moduleName; - - private Statement[] statements; - - this(string moduleName) - { - this.moduleName = moduleName; - } - - public void addStatement(Statement statement) - { - statements ~= statement; - } - - public static StatementType[] getAllOf(StatementType)(StatementType, Statement[] statements) - { - StatementType[] statementsMatched; - - foreach(Statement statement; statements) - { - /* TODO: Remove null, this is for unimpemented */ - if(statement !is null && cast(StatementType)statement) - { - statementsMatched ~= cast(StatementType)statement; - } - } - - return statementsMatched; - } - - public Variable[] getGlobals() - { - Variable[] variables; - - foreach(Statement statement; statements) - { - if(typeid(statement) == typeid(Variable)) - { - variables ~= cast(Variable)statement; - } - } - - return variables; - } - - /* TODO: Make this use weights */ - public Statement[] getStatements() - { - /* Re-ordered by lowest wieght first */ - Statement[] stmntsRed; - - bool wCmp(Statement lhs, Statement rhs) - { - return lhs.weight < rhs.weight; - } - import std.algorithm.sorting; - stmntsRed = sort!(wCmp)(statements).release; - - - return stmntsRed; - } + // TODO: Make use of this } public class Statement From 210fa80c706725bc189549b6b9cf66b71ebbb1c0 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 14:01:07 +0200 Subject: [PATCH 06/28] Data - Removed TODO which is so old idk --- source/tlang/compiler/symbols/data.d | 9 --------- 1 file changed, 9 deletions(-) diff --git a/source/tlang/compiler/symbols/data.d b/source/tlang/compiler/symbols/data.d index 42ccb3ff8..d97a488d6 100644 --- a/source/tlang/compiler/symbols/data.d +++ b/source/tlang/compiler/symbols/data.d @@ -10,15 +10,6 @@ import gogga; // AST manipulation interfaces import tlang.compiler.symbols.mcro : MStatementSearchable, MStatementReplaceable, MCloneable; -/** -* TODO: Implement the blow and use them -* -* These are just to use for keeping track of what -* valid identifiers are. -* -* Actually it might be, yeah it will -*/ - public class Program { // TODO: Make use of this From 2860c654b3519549b95dc3605988fc76f403a408 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 14:06:13 +0200 Subject: [PATCH 07/28] Data - `Program` now has a default constructor and a list of `Module[]` - You can now add a `Module` via the `addModule(Module)` method --- source/tlang/compiler/symbols/data.d | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/source/tlang/compiler/symbols/data.d b/source/tlang/compiler/symbols/data.d index d97a488d6..5b3179815 100644 --- a/source/tlang/compiler/symbols/data.d +++ b/source/tlang/compiler/symbols/data.d @@ -12,7 +12,26 @@ import tlang.compiler.symbols.mcro : MStatementSearchable, MStatementReplaceable public class Program { - // TODO: Make use of this + /** + * Modules this program is made up of + */ + private Module[] modules; + + this() + { + + } + + /** + * Adds a new `Module` to this program + * + * Params: + * newModule = the new `Module` to add + */ + public void addModule(Module newModule) + { + this.modules ~= newModule; + } } public class Statement From 7f4de94c89515c623ce43105c36ebb1002e8cfe4 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 14:13:20 +0200 Subject: [PATCH 08/28] Data - Added documentation for the `Program` class --- source/tlang/compiler/symbols/data.d | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/tlang/compiler/symbols/data.d b/source/tlang/compiler/symbols/data.d index 5b3179815..a554882c0 100644 --- a/source/tlang/compiler/symbols/data.d +++ b/source/tlang/compiler/symbols/data.d @@ -10,6 +10,10 @@ import gogga; // AST manipulation interfaces import tlang.compiler.symbols.mcro : MStatementSearchable, MStatementReplaceable, MCloneable; +/** + * Represents a program made up of one or more + * module(s) + */ public class Program { /** From 2751519f5a5e3d06af26947e750376a9fc83767a Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 14:13:45 +0200 Subject: [PATCH 09/28] Parser - Added module-level check for the `import` statement. Will now call `parseImport()` (which is a work-in-progress) --- source/tlang/compiler/parsing/core.d | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/source/tlang/compiler/parsing/core.d b/source/tlang/compiler/parsing/core.d index 72b8e25a0..9837b1f2a 100644 --- a/source/tlang/compiler/parsing/core.d +++ b/source/tlang/compiler/parsing/core.d @@ -2203,6 +2203,20 @@ public final class Parser return externStmt; } + /** + * Parses an `import ;` statement + */ + private void parseImport() + { + /* Consume the `import` keyword */ + lexer.nextToken(); + + /* Get the module's name */ + expect(SymbolType.IDENT_TYPE, lexer.getCurrentToken()); + string moduleName = lexer.getCurrentToken().getToken(); + + } + /* Almost like parseBody but has more */ /** @@ -2303,6 +2317,12 @@ public final class Parser modulle.addStatement(externStatement); } + /* If it is an import */ + else if(symbol == SymbolType.IMPORT) + { + // TODO: Figure out exactly what to do + parseImport(); + } else { expect("parse(): Unknown '" ~ tok.getToken() ~ "'"); From 22256f921a1990de2349f6fe9a2e160b1c457540 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 14:19:11 +0200 Subject: [PATCH 10/28] Parser - Consume identifier, then expect a semi-colon and consume it - Added TODO for adding multi-module import support in the future --- source/tlang/compiler/parsing/core.d | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/tlang/compiler/parsing/core.d b/source/tlang/compiler/parsing/core.d index 9837b1f2a..621d8e439 100644 --- a/source/tlang/compiler/parsing/core.d +++ b/source/tlang/compiler/parsing/core.d @@ -2215,6 +2215,14 @@ public final class Parser expect(SymbolType.IDENT_TYPE, lexer.getCurrentToken()); string moduleName = lexer.getCurrentToken().getToken(); + /* Consume the token */ + lexer.nextToken(); + + /* Expect a semi-colon and consume it */ + expect(SymbolType.SEMICOLON, lexer.getCurrentToken()); + lexer.nextToken(); + + // TODO: Add support for multi-imports on one line (i.e. `import , ;`) } From 0efa2697781606e615c95a4ab6844a5af6a0d5a3 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 14:21:11 +0200 Subject: [PATCH 11/28] Parser - Added enter/leave debug prints Test cases - Added `modules/a.t` and `modules/b.t` --- source/tlang/compiler/parsing/core.d | 4 ++++ source/tlang/testing/modules/a.t | 3 +++ source/tlang/testing/modules/b.t | 2 ++ 3 files changed, 9 insertions(+) create mode 100644 source/tlang/testing/modules/a.t create mode 100644 source/tlang/testing/modules/b.t diff --git a/source/tlang/compiler/parsing/core.d b/source/tlang/compiler/parsing/core.d index 621d8e439..a5fd94be6 100644 --- a/source/tlang/compiler/parsing/core.d +++ b/source/tlang/compiler/parsing/core.d @@ -2208,6 +2208,8 @@ public final class Parser */ private void parseImport() { + gprintln("parseImport(): Enter", DebugType.WARNING); + /* Consume the `import` keyword */ lexer.nextToken(); @@ -2223,6 +2225,8 @@ public final class Parser lexer.nextToken(); // TODO: Add support for multi-imports on one line (i.e. `import , ;`) + + gprintln("parseImport(): Leave", DebugType.WARNING); } diff --git a/source/tlang/testing/modules/a.t b/source/tlang/testing/modules/a.t new file mode 100644 index 000000000..7214e7501 --- /dev/null +++ b/source/tlang/testing/modules/a.t @@ -0,0 +1,3 @@ +module a; + +import b; \ No newline at end of file diff --git a/source/tlang/testing/modules/b.t b/source/tlang/testing/modules/b.t new file mode 100644 index 000000000..50177ee65 --- /dev/null +++ b/source/tlang/testing/modules/b.t @@ -0,0 +1,2 @@ +module b; + From ee4c6f062554ba25ef9d56b54b2f2740be050651 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 14:22:40 +0200 Subject: [PATCH 12/28] Compiler - Added TODO for `gibFileData(string)` and also made it `public` --- source/tlang/compiler/core.d | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/tlang/compiler/core.d b/source/tlang/compiler/core.d index be2bb2f8d..8037b8e08 100644 --- a/source/tlang/compiler/core.d +++ b/source/tlang/compiler/core.d @@ -247,6 +247,8 @@ public class Compiler } } +// TODO: Move the below to utils +// TODO: Make it do error checking on the path provided and file-access rights /** * Opens the source file at the given path, reads the data * and returns it @@ -255,7 +257,7 @@ public class Compiler * sourceFile = the path to the file to open * Returns: the source data */ -private string gibFileData(string sourceFile) +public string gibFileData(string sourceFile) { File sourceFileFile; sourceFileFile.open(sourceFile); /* TODO: Error handling with ANY file I/O */ From c94c3f179a575287b29f7490803d4f7d18aaedad Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 14:52:34 +0200 Subject: [PATCH 13/28] Containers - `Module` now has a disk file path which can be set with `setFilePath(string)` and retrieved with `getFilePaht()` --- source/tlang/compiler/symbols/containers.d | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/source/tlang/compiler/symbols/containers.d b/source/tlang/compiler/symbols/containers.d index 3b9463e26..d69f42c55 100644 --- a/source/tlang/compiler/symbols/containers.d +++ b/source/tlang/compiler/symbols/containers.d @@ -46,11 +46,38 @@ public interface Container : MStatementSearchable, MStatementReplaceable public class Module : Entity, Container { + /** + * Path to the module on disk + */ + private string moduleFilePath; + this(string moduleName) { super(moduleName); } + /** + * Returns the file system path where + * this module was parsed from + * + * Returns: the path as a `string` + */ + public string getFilePath() + { + return this.moduleFilePath; + } + + /** + * Sets the file system path to the module + * + * Params: + * filePath = path to the module on disk + */ + public void setFilePath(string filePath) + { + this.moduleFilePath = filePath; + } + private Statement[] statements; From ab4ddc75bf165faf48d430f75d0c7c539a221201 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 14:53:03 +0200 Subject: [PATCH 14/28] Parser - Added `getWorkingDirectory()` - `parse()` is now `parse(string)` with a default argument --- source/tlang/compiler/parsing/core.d | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/source/tlang/compiler/parsing/core.d b/source/tlang/compiler/parsing/core.d index a5fd94be6..4eceb0de6 100644 --- a/source/tlang/compiler/parsing/core.d +++ b/source/tlang/compiler/parsing/core.d @@ -2223,12 +2223,29 @@ public final class Parser /* Expect a semi-colon and consume it */ expect(SymbolType.SEMICOLON, lexer.getCurrentToken()); lexer.nextToken(); - // TODO: Add support for multi-imports on one line (i.e. `import , ;`) + import tlang.compiler.core : gibFileData; + + // TODO: Read in here + string workDir = getWorkingDirectory(); + gprintln("Current working directory is: '"~workDir~"'"); + + + + gprintln("parseImport(): Leave", DebugType.WARNING); } + import std.path; + + private static string getWorkingDirectory() + { + // TOOD: look at lazy, seems cool + string workDir = absolutePath("."); + return workDir; + } + /* Almost like parseBody but has more */ /** @@ -2237,7 +2254,7 @@ public final class Parser * one to define classes within functions */ /* TODO: Variables should be allowed to have letters in them and underscores */ - public Module parse() + public Module parse(string moduleFilePath = "") { gprintln("parse(): Enter", DebugType.WARNING); @@ -2258,6 +2275,9 @@ public final class Parser /* Initialize Module */ modulle = new Module(programName); + /* Set the file system path of this module */ + modulle.setFilePath(moduleFilePath); + /* TODO: do `lexer.hasTokens()` check */ /* TODO: We should add `lexer.hasTokens()` to the `lexer.nextToken()` */ /* TODO: And too the `getCurrentTokem()` and throw an error when we have ran out rather */ From 221382c8db20fced26e4b9e3638ecae45313bed6 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 15:14:35 +0200 Subject: [PATCH 15/28] Compiler - Now we take in the input module's file path upon construction - We also pass this to the `parse(string)` call on the `Parser` --- source/tlang/compiler/core.d | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/source/tlang/compiler/core.d b/source/tlang/compiler/core.d index 8037b8e08..813d437c1 100644 --- a/source/tlang/compiler/core.d +++ b/source/tlang/compiler/core.d @@ -95,6 +95,9 @@ public class Compiler /* The input source code */ private string inputSource; + /* Input file path */ + private string inputFilePath; + /* The lexer */ private LexerInterface lexer; @@ -124,14 +127,17 @@ public class Compiler /** * Create a new compiler instance to compile the given * source code + * * Params: * sourceCode = the source code to compile + */ - this(string sourceCode, File emitOutFile) + this(string sourceCode, string inputFilePath, File emitOutFile) { this.inputSource = sourceCode; + this.inputFilePath = inputFilePath; this.emitOutFile = emitOutFile; - + /* Get the default config */ this.config = CompilerConfiguration.defaultConfig(); } @@ -170,7 +176,7 @@ public class Compiler /* Spawn a new parser with the provided tokens */ this.parser = new Parser(lexer); - modulle = parser.parse(); + modulle = parser.parse(this.inputFilePath); } } @@ -299,7 +305,7 @@ void beginCompilation(string[] sourceFiles) outFile.open("tlangout.c", "w"); /* Create a new compiler */ - Compiler compiler = new Compiler(cast(string)fileBytes, outFile); + Compiler compiler = new Compiler(cast(string)fileBytes, sourceFile, outFile); /* Perform the compilation */ compiler.compile(); From 2fbebe22453fa69eb1f8bbf3c10bfc0f879964ad Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 15:15:06 +0200 Subject: [PATCH 16/28] Commands - Updated to new `Compiler` API --- source/tlang/commandline/commands.d | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/tlang/commandline/commands.d b/source/tlang/commandline/commands.d index 54363b501..a43f79447 100644 --- a/source/tlang/commandline/commands.d +++ b/source/tlang/commandline/commands.d @@ -149,7 +149,7 @@ struct compileCommand /* Begin lexing process */ File outFile; outFile.open(outputFilename, "w"); - Compiler compiler = new Compiler(sourceText, outFile); + Compiler compiler = new Compiler(sourceText, sourceFile, outFile); /* Setup general configuration parameters */ BaseCommandInit(compiler); @@ -217,7 +217,7 @@ struct lexCommand file.close(); /* Begin lexing process */ - Compiler compiler = new Compiler(sourceText, File()); + Compiler compiler = new Compiler(sourceText, sourceFile, File()); /* Setup general configuration parameters */ BaseCommandInit(compiler); @@ -263,7 +263,7 @@ struct parseCommand file.close(); /* Begin lexing process */ - Compiler compiler = new Compiler(sourceText, File()); + Compiler compiler = new Compiler(sourceText, sourceFile, File()); /* Setup general configuration parameters */ BaseCommandInit(compiler); @@ -312,7 +312,7 @@ struct typecheckCommand file.close(); /* Begin lexing process */ - Compiler compiler = new Compiler(sourceText, File()); + Compiler compiler = new Compiler(sourceText, sourceFile, File()); /* Setup general configuration parameters */ BaseCommandInit(compiler); From 28b9df2def84605d24738856064339c73609beab Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 15:15:41 +0200 Subject: [PATCH 17/28] Parser - Print out the `Module` that was just parsed's name and file path after parsing it in `parse(string)` --- source/tlang/compiler/parsing/core.d | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/tlang/compiler/parsing/core.d b/source/tlang/compiler/parsing/core.d index 4eceb0de6..a5e66bbe0 100644 --- a/source/tlang/compiler/parsing/core.d +++ b/source/tlang/compiler/parsing/core.d @@ -2366,6 +2366,9 @@ public final class Parser /* Parent each Statement to the container (the module) */ parentToContainer(modulle, modulle.getStatements()); + + gprintln("Done parsing module '"~modulle.getName()~"' from file '"~modulle.getFilePath()~"'"); + return modulle; } } From 350fd8e4aa52013197fc9b2253189910b134f81a Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 15:20:35 +0200 Subject: [PATCH 18/28] Compiler (unit tests) - Fixed compilation error due to us not passing in the input file path to the newly created `Compiler` object --- source/tlang/compiler/core.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/tlang/compiler/core.d b/source/tlang/compiler/core.d index 813d437c1..04edc6910 100644 --- a/source/tlang/compiler/core.d +++ b/source/tlang/compiler/core.d @@ -442,7 +442,7 @@ unittest { File tmpFile; tmpFile.open("/tmp/bruh", "wb"); - Compiler compiler = new Compiler(sourceText, tmpFile); + Compiler compiler = new Compiler(sourceText, testFileGood, tmpFile); // Lex compiler.doLex(); @@ -502,7 +502,7 @@ unittest { File tmpFile; tmpFile.open("/tmp/bruh", "wb"); - Compiler compiler = new Compiler(sourceText, tmpFile); + Compiler compiler = new Compiler(sourceText, testFileFail, tmpFile); // Lex compiler.doLex(); From 0928b65989c502d0841f4efa5cef041961205b9c Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 16:18:36 +0200 Subject: [PATCH 19/28] Parser - `parseImport()` is now `parseImport(string)` and takes in the path to the currently-being-parsed module's file path - Added some work in `parseImport(string)` to extract required details about the current module and the one being imported --- source/tlang/compiler/parsing/core.d | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/source/tlang/compiler/parsing/core.d b/source/tlang/compiler/parsing/core.d index a5e66bbe0..2344e087f 100644 --- a/source/tlang/compiler/parsing/core.d +++ b/source/tlang/compiler/parsing/core.d @@ -2203,10 +2203,14 @@ public final class Parser return externStmt; } - /** - * Parses an `import ;` statement + /** + * Parses module import statements + * + * Params: + * currentModulePath = the path to the current module + * being parsed */ - private void parseImport() + private void parseImport(string currentModulePath) { gprintln("parseImport(): Enter", DebugType.WARNING); @@ -2226,10 +2230,22 @@ public final class Parser // TODO: Add support for multi-imports on one line (i.e. `import , ;`) import tlang.compiler.core : gibFileData; + import std.string : strip; // TODO: Read in here string workDir = getWorkingDirectory(); gprintln("Current working directory is: '"~workDir~"'"); + gprintln("Current module's path: '"~currentModulePath~"'"); + string moduleDir = dirName(currentModulePath); + gprintln("Working directory based on current module's path: '"~moduleDir~"'"); + string curModuleName = strip(pathSplitter(currentModulePath).back(), ".t"); + gprintln("Current module name: '"~curModuleName~"'"); + + + // TODO: Be able to split by `.` and lookup modules via that in FS + gprintln("Module to import: '"~moduleName~"'"); + + @@ -2353,7 +2369,7 @@ public final class Parser else if(symbol == SymbolType.IMPORT) { // TODO: Figure out exactly what to do - parseImport(); + parseImport(moduleFilePath); } else { From 46388e522ebb07073d72ecfa0085dd16b7e75bb5 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 16:46:41 +0200 Subject: [PATCH 20/28] Test cases - Added `niks/c.t` and `z.t` --- source/tlang/testing/modules/niks/c.t | 0 source/tlang/testing/modules/z.t | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 source/tlang/testing/modules/niks/c.t create mode 100644 source/tlang/testing/modules/z.t diff --git a/source/tlang/testing/modules/niks/c.t b/source/tlang/testing/modules/niks/c.t new file mode 100644 index 000000000..e69de29bb diff --git a/source/tlang/testing/modules/z.t b/source/tlang/testing/modules/z.t new file mode 100644 index 000000000..e69de29bb From 3f7c367d151650d6099c9ab62f4f79b55cbda99f Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 16:47:17 +0200 Subject: [PATCH 21/28] Parser - `findModulesInDirectory(string directory)` now will search the directory, exclude all non-files and only return an array of files ending in `.t` - It also will only do a shallow scan (will not recurse into any directories) --- source/tlang/compiler/parsing/core.d | 37 ++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/source/tlang/compiler/parsing/core.d b/source/tlang/compiler/parsing/core.d index 2344e087f..72a713950 100644 --- a/source/tlang/compiler/parsing/core.d +++ b/source/tlang/compiler/parsing/core.d @@ -2245,6 +2245,9 @@ public final class Parser // TODO: Be able to split by `.` and lookup modules via that in FS gprintln("Module to import: '"~moduleName~"'"); + + string[] modulesInStartingDir = findModulesFromStartingPath(currentModulePath); + @@ -2255,6 +2258,40 @@ public final class Parser import std.path; + private static string[] findModulesFromStartingPath(string startingModulePath) + { + // Get directory the mdoule path resides in + string startingDir = dirName(startingModulePath); + + // strip(pathSplitter(currentModulePath).back(), ".t"); + + return findModulesInDirectory(startingDir); + } + + import std.file; + import std.string : endsWith, strip; + private static string[] findModulesInDirectory(string directory) + { + string[] modulesFound; + scope(exit) + { + gprintln("findModulesInDirectory("~directory~"): "~to!(string)(modulesFound)); + } + + foreach(DirEntry entry; dirEntries!()(directory, SpanMode.shallow)) + { + // gprintln(entry); + if(entry.isFile() && endsWith(entry.name(), ".t")) + { + string moduleName = entry.name().strip(".t"); + modulesFound ~= moduleName; + } + } + + + return modulesFound; + } + private static string getWorkingDirectory() { // TOOD: look at lazy, seems cool From 0f8c544f9664b3350cf5d16361a34b83bcc5ec4c Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 16:55:42 +0200 Subject: [PATCH 22/28] Parser - Now search the modules in our starting directory to see if the one requested to be imported lies within - Throw an error if not found --- source/tlang/compiler/parsing/core.d | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/source/tlang/compiler/parsing/core.d b/source/tlang/compiler/parsing/core.d index 72a713950..c4454ffd6 100644 --- a/source/tlang/compiler/parsing/core.d +++ b/source/tlang/compiler/parsing/core.d @@ -2248,6 +2248,29 @@ public final class Parser string[] modulesInStartingDir = findModulesFromStartingPath(currentModulePath); + // TODO: We need to do proper lookups for non-relative module names used + // ... in import statements + bool found = false; + foreach(string cmnPath; modulesInStartingDir) + { + string cmn = pathSplitter(cmnPath).back(); + if(cmp(cmn, moduleName) == 0) + { + found = true; + break; + } + } + + if(found) + { + + } + else + { + // TODO: Make nicer error? + expect("Could not find module '"~moduleName~"' which was requested to be imported"); + } + From 261dbf5ec13739e28451737fc404721e69520cba Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sun, 27 Aug 2023 17:32:30 +0200 Subject: [PATCH 23/28] Parser - `findModulesInDirectory(string directory)` now replaces all the `/` with `.`'s --- source/tlang/compiler/parsing/core.d | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/source/tlang/compiler/parsing/core.d b/source/tlang/compiler/parsing/core.d index c4454ffd6..4f7ec0c1e 100644 --- a/source/tlang/compiler/parsing/core.d +++ b/source/tlang/compiler/parsing/core.d @@ -2251,10 +2251,9 @@ public final class Parser // TODO: We need to do proper lookups for non-relative module names used // ... in import statements bool found = false; - foreach(string cmnPath; modulesInStartingDir) + foreach(string cmn; modulesInStartingDir) { - string cmn = pathSplitter(cmnPath).back(); - if(cmp(cmn, moduleName) == 0) + if(endsWith(cmn, moduleName)) { found = true; break; @@ -2263,7 +2262,7 @@ public final class Parser if(found) { - + // TODO: Implement this } else { @@ -2293,6 +2292,8 @@ public final class Parser import std.file; import std.string : endsWith, strip; + // TODO: Probably replavce the slashes with `.` + // ... such that `niks/c.t` becomes `niks.c` private static string[] findModulesInDirectory(string directory) { string[] modulesFound; @@ -2311,10 +2312,21 @@ public final class Parser } } + // Replace all `/`'s with `.`s + import std.algorithm.iteration : map; + import std.array : array; + modulesFound = map!(slashToDot)(modulesFound).array(); + return modulesFound; } + import std.string : replace; + private static string slashToDot(string strIn) + { + return replace(strIn, "/", "."); + } + private static string getWorkingDirectory() { // TOOD: look at lazy, seems cool From 13bea632b2911c037b1c2ae01a9085c120b812d9 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Fri, 27 Oct 2023 12:07:10 +0200 Subject: [PATCH 24/28] ModMan - Added stub `ModuleManager` --- source/tlang/compiler/parsing/modman.d | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 source/tlang/compiler/parsing/modman.d diff --git a/source/tlang/compiler/parsing/modman.d b/source/tlang/compiler/parsing/modman.d new file mode 100644 index 000000000..6c49f4648 --- /dev/null +++ b/source/tlang/compiler/parsing/modman.d @@ -0,0 +1,9 @@ +module tlang.compiler.parsing.modman; + +/** + * Manager for searching for modules etc. + */ +public final class ModuleManager +{ + +} \ No newline at end of file From 70da08010b6bbd28721c6b38dba18897b8f2e9ec Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Fri, 27 Oct 2023 12:21:08 +0200 Subject: [PATCH 25/28] ModuleManager - Added `validate(string searchPath)` - Added `validate(string[] searchPaths)` - Added a constructor ModMan (unitests) - Added a positive unittest --- source/tlang/compiler/parsing/modman.d | 83 ++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/source/tlang/compiler/parsing/modman.d b/source/tlang/compiler/parsing/modman.d index 6c49f4648..70c0d01e4 100644 --- a/source/tlang/compiler/parsing/modman.d +++ b/source/tlang/compiler/parsing/modman.d @@ -1,9 +1,92 @@ module tlang.compiler.parsing.modman; +import gogga; + /** * Manager for searching for modules etc. */ public final class ModuleManager { + /** + * The search paths + */ + private string[] searchPaths; + + /** + * Creates a new module manager with the + * provided paths of which it should + * consider when searching for module + * files + * + * Params: + * searchPaths = the search paths + */ + this(string[] searchPaths) + { + validate(searchPaths); + this.searchPaths = searchPaths; + } + + /** + * Validates the given paths, and only + * returns a valid verdict if all of + * the paths are valid search paths + * + * Params: + * searchPaths = the search paths + * to consider + * Returns: `true` if all paths are valid, + * `false` otherwise + */ + public static bool validate(string[] searchPaths) + { + foreach(string searchPath; searchPaths) + { + if(!validate(searchPath)) + { + return false; + } + } + + return true; + } + + /** + * Validates a given path that it is a valid + * search path + * + * Params: + * searchPath = the path to check + * Returns: `true` if the search path is valid, + * `false` otherwise + */ + public static bool validate(string searchPath) + { + // Path cannot be empty + if(searchPath.length == 0) + { + return false; + } + + import std.file : isDir; + + // It should be a valid directory + return isDir(searchPath); + } +} + +/** + * Tests the static methods of the `ModuleManager` + * + * In this case positive verdict is expected + */ +unittest +{ + string[] goodPaths = [ + "source/tlang/testing", + "source/tlang/testing/modules" + ]; + bool res = ModuleManager.validate(goodPaths); + assert(res); } \ No newline at end of file From ba9e1f08f445dffb290273da4ef9a5b08642fe9d Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Fri, 27 Oct 2023 12:25:19 +0200 Subject: [PATCH 26/28] ModMan (unittests) - Added negative test case example --- source/tlang/compiler/parsing/modman.d | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/source/tlang/compiler/parsing/modman.d b/source/tlang/compiler/parsing/modman.d index 70c0d01e4..98ac85005 100644 --- a/source/tlang/compiler/parsing/modman.d +++ b/source/tlang/compiler/parsing/modman.d @@ -89,4 +89,22 @@ unittest bool res = ModuleManager.validate(goodPaths); assert(res); -} \ No newline at end of file +} + +/** + * Tests the static methods of the `ModuleManager` + * + * In this case negative verdict is expected + */ +unittest +{ + string[] badPaths = [ + "source/tlang/testing", + "source/tlang/testing/modules", + "README.md", + ]; + + bool res = ModuleManager.validate(badPaths); + assert(!res); +} + From 0d565af930d86e641d28eef24af7d8579752d3ce Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Fri, 27 Oct 2023 12:30:48 +0200 Subject: [PATCH 27/28] ModMan - Moved to new package --- source/tlang/compiler/{parsing => modman}/modman.d | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) rename source/tlang/compiler/{parsing => modman}/modman.d (97%) diff --git a/source/tlang/compiler/parsing/modman.d b/source/tlang/compiler/modman/modman.d similarity index 97% rename from source/tlang/compiler/parsing/modman.d rename to source/tlang/compiler/modman/modman.d index 98ac85005..a56365978 100644 --- a/source/tlang/compiler/parsing/modman.d +++ b/source/tlang/compiler/modman/modman.d @@ -1,4 +1,4 @@ -module tlang.compiler.parsing.modman; +module tlang.compiler.modman.modman; import gogga; @@ -20,6 +20,8 @@ public final class ModuleManager * * Params: * searchPaths = the search paths + * Throws: + * */ this(string[] searchPaths) { From 63e8b600c7cf07149b7553a1b4b9165656384b88 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Fri, 27 Oct 2023 12:33:10 +0200 Subject: [PATCH 28/28] ModMan - Added exception class ModuleManager - Throw an exception ( a `ModuleManagerError`), if one of the search paths is invalid during construction --- source/tlang/compiler/modman/exceptions.d | 12 ++++++++++++ source/tlang/compiler/modman/modman.d | 13 +++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 source/tlang/compiler/modman/exceptions.d diff --git a/source/tlang/compiler/modman/exceptions.d b/source/tlang/compiler/modman/exceptions.d new file mode 100644 index 000000000..5f7890139 --- /dev/null +++ b/source/tlang/compiler/modman/exceptions.d @@ -0,0 +1,12 @@ +module tlang.compiler.modman.exceptions; + +import misc.exceptions; +import tlang.compiler.modman.modman : ModuleManager; + +public final class ModuleManagerError : TError +{ + this(ModuleManager modMan, string msg) + { + super("Module manager '"~modMan.toString()~"' had error: "~msg); + } +} \ No newline at end of file diff --git a/source/tlang/compiler/modman/modman.d b/source/tlang/compiler/modman/modman.d index a56365978..aca8a5ece 100644 --- a/source/tlang/compiler/modman/modman.d +++ b/source/tlang/compiler/modman/modman.d @@ -2,6 +2,10 @@ module tlang.compiler.modman.modman; import gogga; +// TODO: We may want to throw an exception whilst searching +// ... as to which path is invalid +import tlang.compiler.modman.exceptions; + /** * Manager for searching for modules etc. */ @@ -21,11 +25,16 @@ public final class ModuleManager * Params: * searchPaths = the search paths * Throws: - * + * ModuleManagerError = if the + * provided search paths are incorrect */ this(string[] searchPaths) { - validate(searchPaths); + if(!validate(searchPaths)) + { + throw new ModuleManagerError(this, "An invalid path exists within the provided search paths"); + } + this.searchPaths = searchPaths; }