From d9c5d1707b45d8c52e81d24764fc13cfa37de142 Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Thu, 12 Dec 2024 16:06:29 +0000 Subject: [PATCH] Allow module reimporting. Pull module from VM if already imported for main path --- docs/docs/standard-lib/importlib.md | 5 +++-- src/optionals/importlib.c | 22 +++++++++++++++++++--- tests/importlib/include.du | 17 +++++++++++++++++ 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/docs/docs/standard-lib/importlib.md b/docs/docs/standard-lib/importlib.md index 76ff3057..f9574b94 100644 --- a/docs/docs/standard-lib/importlib.md +++ b/docs/docs/standard-lib/importlib.md @@ -23,11 +23,12 @@ To make use of the Importlib module an import is required. import Importlib; ``` -### Importlib.include(String) -> Module +### Importlib.include(String, Bool: reload -> Optional) -> Module -This allows you to dynamically import a module. +This allows you to dynamically import a module. It also allows you to reload a module that was previously imported. Note: The path is relative to the file include() is called in. +Note: Reloading an already imported module will mutate all references to the previously imported module. ```js // someFile.du diff --git a/src/optionals/importlib.c b/src/optionals/importlib.c index 0345258c..354aca55 100644 --- a/src/optionals/importlib.c +++ b/src/optionals/importlib.c @@ -1,16 +1,27 @@ #include "importlib.h" Value includeNative(DictuVM *vm, int argCount, Value *args) { - if (argCount != 1) { - runtimeError(vm, "include() takes 1 argument (%d given)", argCount); + if (argCount != 1 && argCount != 2) { + runtimeError(vm, "include() takes 1 or 2 arguments (%d given)", argCount); return EMPTY_VAL; } if (!IS_STRING(args[0])) { - runtimeError(vm, "include() argument must be a string"); + runtimeError(vm, "include() first argument must be a string"); return EMPTY_VAL; } + bool reload = false; + + if (argCount == 2) { + if (!IS_BOOL(args[1])) { + runtimeError(vm, "include() second argument must be a boolean"); + return EMPTY_VAL; + } + + reload = AS_BOOL(args[1]); + } + CallFrame *frame = &vm->frames[vm->frameCount - 1]; char path[PATH_MAX]; @@ -19,7 +30,12 @@ Value includeNative(DictuVM *vm, int argCount, Value *args) { return EMPTY_VAL; } + Value moduleVal; ObjString *pathObj = copyString(vm, path, strlen(path)); + if (!reload && tableGet(&vm->modules, pathObj, &moduleVal)) { + return moduleVal; + } + push(vm, OBJ_VAL(pathObj)); ObjModule *module = newModule(vm, pathObj); pop(vm); diff --git a/tests/importlib/include.du b/tests/importlib/include.du index 4308ce49..049cdcf8 100644 --- a/tests/importlib/include.du +++ b/tests/importlib/include.du @@ -20,6 +20,23 @@ class TestImportLibInclude < UnitTest { this.assertType(Level1.Level2.Level3, 'module'); this.assertEquals(Level1.Level2.Level3.list, [1, 2, 3]); } + + testImportLibIncludeReload() { + // reset test file + with('tests/importlib/data/test.du', 'w') { + file.write('var test = 10;'); + } + + const TestModule = Importlib.include('data/test.du'); + this.assertEquals(TestModule.test, 10); + + with('tests/importlib/data/test.du', 'w') { + file.write('var test = 100;'); + } + + const TestModuleReimport = Importlib.include('data/test.du', true); + this.assertEquals(TestModuleReimport.test, 100); + } } TestImportLibInclude().run(); \ No newline at end of file