Skip to content

Commit bd5f6b1

Browse files
add stdlib image extension and import-time extension loading
SPECIFICATION.html Document IMPORT-time extension loading: interpreter will look for a companion <module>.asmxt next to the resolved module (or in lib/ fallback) and will also check the built-in ext/ directory for a single-file extension <module>.py. Extensions listed/located there are loaded at IMPORT so their operators are immediately available to the importer. ext/image.py New standard-library-only image extension providing three operators: LOAD_PNG(path), LOAD_JPEG(path), LOAD_BMP(path) -> TNS[height][width][r,g,b,a]. Prefers Windows GDI+ via ctypes for broad codec support and performance; falls back to pure-Python decoders for non-interlaced 8-bit PNG and uncompressed 24/32-bit BMP on non-Windows platforms. JPEG decoding available only when GDI+ is present. Performs argument and size validation, converts pixel data into interpreter Tensor/Value objects, and registers operators via the ExtensionAPI. Includes API version checks and clear error reporting. interpreter.py On IMPORT, attempt to load companion .asmxt and builtin ext/<module>.py extensions: Read .asmxt to gather extension paths and load each extension module. Validate extension API version and presence of callable asm_lang_register. Call asm_lang_register(ext_api) and register any new operators into the running interpreter, avoiding duplicate registrations. ASMExtensionError during extension loading is surfaced as a runtime error; other exceptions are non-fatal and do not prevent importing the module. Ensures operators provided by extensions are attached to the interpreter at import time so the importer can call them immediately. lib/ Add lib/image.asmln helper library (ASM-level helpers that accompany the extension). Add lib/image.asmxt pointer file referencing image.py. Update lib/path.asmln: add clarifying comments and small fixes to BASEPATH, BASENAME, SPLITEXT, EXTNAME, DELEXT signatures/comments. test.asmln Import image library and add a smoke test that loads sample icon.bmp, icon.png and icon.jpg from the interpreter dir and asserts equality (verifies LOAD_BMP/LOAD_PNG/LOAD_JPEG). assets Add sample image assets icon.bmp and icon.jpg used by tests.
1 parent 0c1ad5e commit bd5f6b1

File tree

10 files changed

+549
-6
lines changed

10 files changed

+549
-6
lines changed

SPECIFICATION.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,17 @@
435435
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`).
436436

437437
This caching behavior ensures that importing a module multiple times produces the same shared module namespace instance for all importers. The interpreter does not automatically perform cycle detection beyond using the cached instance once execution has completed; careful module design should avoid import cycles where possible.
438+
439+
When a module is imported, the interpreter also attempts to load any associated runtime
440+
extensions so their operators are immediately available to the importer. The
441+
interpreter first looks for a companion pointer file named `<module>.asmxt`
442+
next to the resolved module file (or in the interpreter `lib/` fallback) and
443+
loads any extensions listed there. If no pointer file is present (or as an
444+
additional fallback), the interpreter will also check its built-in `ext/`
445+
directory for a single-file extension named `<module>.py` and load it if
446+
present. Operators registered by such extensions are attached to the running
447+
interpreter at import time and become callable (typically under the
448+
module-qualified names they register).
438449
- `EXPORT(SYMBOL: symbol, MODULE: module):INT` Adds the caller's binding for the identifier `symbol` into the namespace of the imported module named by the identifier `module`. The first argument must be an identifier (not a string literal); its current value in the caller's environment is copied into the imported module's namespace and becomes available as the qualified name `module.symbol` in the caller's environment. The second argument must be an identifier naming a previously-imported module; if the module has not been imported yet, the interpreter raises a runtime error (rewrite: EXPORT). `EXPORT` returns `INT` 0 on success.
439450
440451
### File operations:

asm-lang.exe

4.11 KB
Binary file not shown.

0 commit comments

Comments
 (0)