Module Scope + def Semantics v0.2
This document is normative for GenesisCode v0.2 evaluation.
Goals
- Make top-level modules usable without special recursion forms.
- Keep the kernel deterministic and pure (no effects).
- Keep lexical scoping for local bindings (
let,fn).
Top-Level Forms
A module is a vector/list of CoreForm terms evaluated left-to-right.
(def <sym> <expr>)
def is only recognized at the top level by the module evaluator.
Semantics:
- Evaluate
<expr>in the current module environment. - Bind the result to
<sym>in the current module scope (overwriting any prior binding for the same name). - The value of a
deftop-form isnil.
Recursive Module Scope
All def bindings in a module share a single module scope frame. That frame is updated as defs are evaluated.
Consequence:
- Closures created earlier in the module can call functions defined later in the module.
- Mutual recursion across top-level definitions works (e.g.,
even?andodd?defined in either order).
This rule is required to support self-hosted tooling modules (printer, canonicalizer, etc.) without adding a dedicated letrec form in v0.2.
Lexical Scope
Local bindings (let, function parameters) are lexical and create nested scope frames. Each source binder is one symbol, and names must be unique within one fn parameter list or one let binding list. This local duplicate rejection does not change the intentional top-level def replacement rule above.
Name lookup is:
- Innermost lexical frame outward through parents.
- Module scope frame (top-level
defbindings).
Hashing Note
Recursive module scope can create cyclic value graphs (a binding closes over the module scope that binds it). Value hashing remains total and deterministic by applying the cycle handling rule defined in docs/spec/VALUE_EFFECT_HASH.md.
Cross-Module Resolution
This document governs recursion and replacement inside one module. Modules that declare genesis/module-resolution-profile-v0.1 additionally follow MODULE_RESOLUTION_PROFILE_v0.1.md: only earlier public exports may be imported, local cross-module imports are explicit, and forward, self, and cyclic module imports fail closed. These rules do not restrict mutual recursion among top-level definitions in the same module.