Modules and Parts
A Lux module is a directory-level unit, not a single file. Every .lux part
file under the module directory contributes to one logical module scope.
This is the central difference from the old package system: developers split a module by concern and realm, while the compiler owns discovery, realm routing, loading, and generated Lua layout.
All four files above are one module named inventory.
Module Scope
Top-level declarations in any part create module-private bindings. Those bindings are visible to every other part in the same module, subject to realm checks.
normalizeItemId is not exported, but it is still visible inside the module.
Export controls external API only; it does not affect internal visibility.
Imports Are Part-local
Top-level imports are local to the part file that declares them. They do not become module-wide bindings.
If sv_store.lux also needs arr, it imports arr itself. This rule keeps
part dependencies visible at the top of each file and prevents a later part from
silently depending on imports from an earlier part.
Function Hoisting
Simple top-level fn declarations are hoisted across the whole module. This is
why part files can call each other without artificial numeric filenames.
Only simple function bindings are hoisted. Declarations with side-effectful initializers are not moved.
Top-level Initialization
Top-level non-function locals are initialized in deterministic part order. They are module-private and visible across parts after initialization, but using them before initialization is an error.
If module.lux read store before sv_store.lux initializes it, Lux reports a
use-before-initialization diagnostic instead of relying on runtime nil
behavior.
Entry Parts
A multi-file module must have exactly one entry part. The entry gives developers a stable place to start reading the module and gives the compiler a stable place for module-level metadata.
Valid entry part names are:
Single-file modules do not need an entry part. A multi-file module without an entry is a compile error.
Part Order
Complete part order belongs in the entry part.
before and after constraints are allowed as auxiliary ordering hints, but a
complete part order is the right tool when you need to fully choreograph a
module.
Lux rejects duplicate part entries, references to missing parts, ambiguous short names, and ordering cycles.
Duplicate Bindings
MVP 0.1 rejects duplicate module-scope binding names, even if the declarations are in different files or different realms.
Use distinct internal names and export aliases when you want the public API to look uniform.
Do Not Import Same-module Parts
Part files in the same module already share module scope. Importing a sibling part by path is a design error because it turns internal organization into a public dependency.
If another module needs a binding, export it from the module API and import the module, not one of its part files.