Skip to main content

Module assemble

Module assemble 

Source
Expand description

Source-level assembly of a multi-file / multi-directory LOGOS project.

A project is ONE compilation unit. assemble_project resolves the entry file’s explicit imports (markdown links in its abstract), transitively loads every reachable module, and splices their code into a single combined source string — the same string-level seam the stdlib prelude already uses (apply_prelude). Because every execution tier (AOT, interpreter, VM, wasm, isa, C) re-parses from a source string, one assembled string feeds them all: the imported functions and types reach the parser, the call graph, and codegen exactly as if the program had been written in a single file.

§Ordering

Modules are collected in post-order DFS over the import graph, so a module’s dependencies are spliced before it and the entry’s own body (with its ## Main) comes last. The tree-walking interpreter registers each ## To definition as it walks and has no hoisting pass, so “definitions before the Main that uses them” must hold structurally — post-order gives it.

§Cycle & diamond safety

Collection dedups by canonical path through a visited set, seeded with the entry. Mutual imports (A uses B, B uses A) are legal — required for cross-file mutual recursion — and contribute each module’s code exactly once. A module that imports the entry back never re-splices the entry’s ## Main.

§Foreign ## Main

Only the ENTRY’s ## Main survives; an imported module contributes its functions and type definitions but never a ## Main (stripped by strip_main_block). This preserves the single-entry-Main contract every tier relies on.

Structs§

AssembledProgram
One assembled compilation unit: the combined source plus the metadata later passes need for qualified-name resolution, collision diagnostics, and cross-file error attribution.
DefSite
A single definition site: which module (canonical path) declared a bare name, and the normalized content of the definition (its identity — two defs with the same normalized body are THE SAME definition).
Located
A combined-source offset resolved back to its origin.
Provenance
Bare-name → the modules that define it. A bare name owned by more than one distinct module is ambiguous: a bare reference to it is a hard error, and the qualified form disambiguates.
ScopeInfo
Per-file lexical scope for the whole project: what each file is allowed to reference. A file sees its own definitions and the exports of the modules it directly imports — never anything reached only transitively.
Segment
One contributed segment of the combined source: its [start, end) byte range in the combined string, the ORIGINAL file it came from, and — for a byte-intact segment — the offset in that file its start corresponds to.
SourceMap
File-level attribution: for each contributed segment of the combined source, its byte range, originating file, and (for byte-intact segments) the offset-within-file mapping — so a diagnostic on the combined blob is attributed to the user’s own file and line.

Enums§

DefKind
The kind of a top-level definition, for collision messages.

Functions§

assemble_project
Assemble the whole project reachable from entry_path into one compilation unit. Returns an error only for unreadable/unresolvable imports; the combined source is then parsed by the normal pipeline.
assemble_project_with_deps
assemble_project, additionally linking the declared dependency roots so a bare Import <Dep>. resolves against a path/git-local package outside the project root. dep_roots empty is byte-for-byte identical to assemble_project, so a single-project build is unchanged.
check_scopes
Enforce per-file scoping over the assembled program: a reference to a name that is another user module’s export, from a file that neither defines nor imports it, is a hard error (no transitive leakage). Builtins, stdlib, and a file’s own/imported names are always fine, so a valid program never trips.