# Modules and require

Every file is a module with its own scope. `require` imports named
definitions from a standard module compiled into the binary or from a file
next to yours.

```lisp
(require "sexpgpu/nn" cross-entropy gpt)       ; a standard module
(require "sexpgpu/optim" adamw warmup-stable-decay)
(require "../lib/mine.sx" my-gpt)              ; a file, relative to this one
```

## Resolution

| path | resolves to |
|---|---|
| `sexpgpu/nn`, `sexpgpu/optim` | the standard modules; see [nn](https://sx.041.io/docs/nn.md) and [optim](https://sx.041.io/docs/optim.md). Anything else under `sexpgpu/` is `E-EVAL-033` |
| `./name.sx`, `../dir/name.sx` | a file, relative to the directory of the file holding the `require`, never to a project root or the working directory |
| anything else | `E-EVAL-032`: a path must start with `./` or `../` |

A file is loaded once per compilation, by canonical path. A cycle is
`E-EVAL-030`, a missing file `E-EVAL-031`. Because paths are relative to
the file, every command works from any working directory.

## Scope

A file sees three things: the [prelude](https://sx.041.io/docs/prelude.md), what it defines, and
the names its `require`s list. It sees nothing a library required in turn.

- Every top-level definition of a file can be imported; there is no export
  list. Generated top-level definitions (from a macro) can be imported too.
- A `require` names at least one definition. Naming something the file does
  not define is `E-EVAL-035`, and the fix is the nearest name it does.
- A name is bound once per file. Two imports of one name, from one module
  or two, or an import and a local definition, are `E-EVAL-036`.
- Every import is used. A name the file writes nowhere but in its
  `require`s is `E-EVAL-037`; take it out. Writing it anywhere counts,
  including on a branch the selected knobs skip, so an optimizer imported
  for `(if (= opt :muon) ...)` is used under every selection. A contract
  name the run file imports, `model` or `train-loader`, is read by the
  compiler and is used.
- Imported names are not re-exported.
- `require` runs at module top level, including inside a top-level `progn`
  or a macro expansion. In a local scope it is `E-EVAL-034`.
- Import a name before writing a function or quoted datum that uses its
  identity; imports do not rewrite symbols already constructed. See
  [macros](https://sx.041.io/docs/macros.md#generated-declarations).

A library macro's expansion keeps the library's symbol identities, so it can
call the library's private helpers without the caller importing them. The
symbols it writes are looked up in the library and then the prelude, never
in the requiring file: a name only the requiring file defines is
`E-EVAL-003`, and the message names the library. See
[macros and symbols](https://sx.041.io/docs/macros.md#symbols-and-capture).

## Writing a library

A library is a plain `.sx` file that your runs `require`. It can hold
models, schedules and constants shared by several runs, and it can require
`sexpgpu/nn` for the generic parts:

```lisp
;;; lib/mine.sx
(require "sexpgpu/nn" rmsnorm linear)

(defvar init-std 0.02)

(defmodel my-gpt (&key vocab layers dim) ...)
```

A library can also carry diagnostics for its models, off until a run
selects them; see [writing diagnostics](https://sx.041.io/docs/writing-diagnostics.md).

A `bundle` flattens every required file into `files/deps/` and rewrites the
paths; see [bundle](https://sx.041.io/docs/bundle.md#layout).

Related: [the run file](https://sx.041.io/docs/run-file.md), [the prelude](https://sx.041.io/docs/prelude.md).

---

SexpGPU documentation. Every page: https://sx.041.io/llms.txt
