v5 Bytecode: compiling modules
- Derive module initialization, imports, and export-map stack effects.
- Distinguish exported values from live bindings.
- Produce reusable local-ID artifacts for relocation.
1 / 6
For module util { export let answer=7; }, initializer code is:
ENTER_SCOPE
PUSH_NUM 7
DEFINE_VAR answer
PUSH_STR "answer"
LOAD answer
MAKE_MAP 1
EXIT_SCOPE
DEFINE_CONST util
The map remains on the operand stack while EXIT_SCOPE discards the temporary module environment from the current frame. DEFINE_CONST installs that map in the surrounding global scope. A function exported from this environment can keep it alive through its closure capture even after EXIT_SCOPE.
For import util as u, the importing module emits LOAD util then DEFINE_CONST
u inside its own initializer scope. u.answer becomes LOAD u, PUSH_STR answer,
GET_INDEX. No new VM member opcode is required; the analyzer already checked
visibility and the compiler uses ordinary map indexing.
A compiler exits the module scope before loading exported values, then tries to build its map. Another puts imported util directly into the importer’s outer globals under alias u. What lifetime/scope information was lost?
Derive initializer instructions for a module exporting one function and one array. Trace the map stack shape, identify which values retain objects/environments, and annotate all operands that the linker will relocate.
Carry independent module artifacts with local coordinates into Link. Keep a saved copy so repeated linking can prove the originals were not modified.