Skip to content

Commit

Permalink
Allow module reimporting. Pull module from VM if already imported for…
Browse files Browse the repository at this point in the history
… main path
  • Loading branch information
Jason2605 committed Dec 12, 2024
1 parent 0013a2e commit d9c5d17
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 5 deletions.
5 changes: 3 additions & 2 deletions docs/docs/standard-lib/importlib.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 19 additions & 3 deletions src/optionals/importlib.c
Original file line number Diff line number Diff line change
@@ -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];

Expand All @@ -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);
Expand Down
17 changes: 17 additions & 0 deletions tests/importlib/include.du
Original file line number Diff line number Diff line change
Expand Up @@ -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();

0 comments on commit d9c5d17

Please sign in to comment.