Skip to main content

Module loader

Module loader 

Source
Expand description

Multi-file loader: resolves import "./...", import "../...", and import "/abs/..." statements relative to the importer, recursively parses, and produces a single Program with all stages merged.

Names that are local to an imported file are mangled with a per-file-path prefix, so the same module imported via multiple aliases (or from multiple parents in a diamond shape) collapses to one set of mangled names — same SigId, same nominal identity. Stdlib imports (import "std.foo" as bar) pass through unchanged.

§Mangling

Each loaded file gets a prefix derived from its canonical filesystem path. The entry file’s prefix is empty (so lex run main.lex process works unchanged). Imported files use <stem>_<hash> where hash is the first 8 hex chars of SHA-256 of the canonical path string. The hash disambiguates same-stem files in different directories without forcing a project manifest.

Within a file at prefix P:

  • fn foo declared in this file becomes <P>.foo (just foo at root).
  • type T declared in this file becomes <P>.T.
  • References to a locally-declared name get mangled, unless the name is shadowed by a binder (let, fn param, lambda param, or pattern binder) in scope.
  • m.foo where m is a path-import alias is rewritten to the imported file’s prefix-qualified name. Two parents importing the same file see the same prefix → calls and types unify.
  • m.foo where m is a stdlib alias is unchanged.

Variant constructors are not mangled — they live in a global namespace, and a collision between two imported types’ constructors surfaces later as a type-check error. Same for record field names.

§Diamond imports

main.lex imports ./left and ./right, both of which import ./shared. shared.lex is parsed once per resolution, but its mangled items are merged into the output exactly once (subsequent loads from the same canonical path return an empty Program). This is what makes s.build_report(...) and v.read_score(...) agree on Report’s nominal identity.

§Limitations (tracked separately)

The mangling key is the canonical filesystem path. Moving a file changes its SigId; renaming changes the file-stem half of the prefix. The eventual fix — content-addressed identity decoupled from filesystem layout — lives with store-native imports (import "stage:..."); see the corresponding follow-up tracker.

Enums§

LoadError

Functions§

load_program
Load a multi-file Lex program, expanding local imports relative to the entry path. Stdlib imports (std.*) pass through unchanged.
load_program_from_str
Load a Lex program from a string source. Local-path imports are rejected up-front since there’s no base path to resolve from.