Skip to content

Commit 3600856

Browse files
gh-30: IMPORT and IMPORT_PATH error when no module is found.
1 parent bb7db40 commit 3600856

File tree

2 files changed

+25
-0
lines changed

2 files changed

+25
-0
lines changed

docs/SPECIFICATION.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,8 @@
835835

836836
The first argument must be an identifier naming a module; the interpreter first looks for a file named `<name>.pre` in the same directory as the referring source file. When the referring source is provided via the `-source` string literal mode, the primary search directory is the process's current working directory. If the module file is not found there, the interpreter will additionally attempt to load the file from a `lib` subdirectory located alongside the interpreter implementation (that is, `<interpreter_dir>/lib/<name>.pre`, where `<interpreter_dir>` is the directory containing the interpreter script or executable).
837837

838+
If no module file is found in any search location, `IMPORT` throws an error.
839+
838840
The imported file is parsed and executed in its own isolated top-level environment on the first import during a given interpreter invocation: top-level assignments and function definitions in the imported module do not directly mutate the caller's environment during execution. During that execution unqualified identifiers (for example, `x` or `helper`) refer to names in the module's own top-level namespace. Qualified identifiers (for example, `other.FOO`) refer only to the dotted names that the module itself has created or imported; those qualified bindings are scoped to the module's namespace.
839841

840842
After the module finishes executing the first time, the interpreter caches the module's top-level environment and the module-qualified function objects. Subsequent `IMPORT` calls for the same module identifier within the same interpreter process reuse that cached namespace/instance and do not re-execute the module source. Callers importing the same module later will observe the same shared module environment (that is, the same binding objects and the same function objects). By default bindings are exposed under the module's own dotted prefix (`module.FOO`, `module.bar`, etc.); however, if the importer supplied an alias the bindings are instead exposed under the alias prefix (`alias.FOO`, `alias.bar`). Multiple different aliases for the same module identifier will each get their own dotted view into the same cached module instance. If the module imported other modules during its execution, those nested qualified bindings are preserved in the cached namespace and remain accessible via the same dotted paths (for example, `module.other.SYM` or `alias.other.SYM` or `module.alias.SYM`).

src/builtins.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4237,6 +4237,16 @@ static Value builtin_import_path(Interpreter* interp, Value* args, int argc, Exp
42374237
char* canonical_path = found_path ? canonicalize_existing_path(found_path) : NULL;
42384238
const char* cache_key = canonical_path ? canonical_path : inpath;
42394239

4240+
// If the path did not resolve to an existing file/dir and the module
4241+
// isn't already registered, treat this as a missing module error.
4242+
if (!found_path) {
4243+
Env* existing = module_env_lookup(interp, cache_key);
4244+
if (!existing) {
4245+
if (alias_dup) free(alias_dup);
4246+
RUNTIME_ERROR(interp, "IMPORT_PATH: module not found", line, col);
4247+
}
4248+
}
4249+
42404250
Env* mod_env = module_env_lookup(interp, cache_key);
42414251
if (!mod_env) {
42424252
if (module_register(interp, cache_key) != 0) {
@@ -6018,6 +6028,19 @@ static Value builtin_import(Interpreter* interp, Value* args, int argc, Expr** a
60186028
char* canonical_path = found_path ? canonicalize_existing_path(found_path) : NULL;
60196029
const char* cache_key = canonical_path ? canonical_path : modname;
60206030

6031+
/* If we couldn't locate a file for the requested module and there is no
6032+
previously-registered module with this name, report a clear error. */
6033+
if (!found_path) {
6034+
Env* existing = module_env_lookup(interp, cache_key);
6035+
if (!existing) {
6036+
free(found_path);
6037+
free(canonical_path);
6038+
char buf[256];
6039+
snprintf(buf, sizeof(buf), "IMPORT: module '%s' not found", modname);
6040+
RUNTIME_ERROR(interp, buf, line, col);
6041+
}
6042+
}
6043+
60216044
/* Attempt to load a companion .prex pointer file next to the resolved
60226045
module file so that any extension libraries listed there are available
60236046
during module execution (e.g. lib/image/init.prex -> win32.dll). */

0 commit comments

Comments
 (0)