# Compiler boundary

Why runtime packages never import the DSL compiler, how module layering enforces it, and the separate schema-module rule.

Runtime packages must never import `dsl`. The compiler turns a `.zen` schema into Go source once; a running service imports only generated output, the container, and adapters. Linking the frontend would bloat every binary and let request-time code special-case schema logic.

## The compile-time pipeline

```text
source text -> lexer -> parser -> ast -> resolver -> ir.Schema
                                     -> compile -> backend outputs
```

Everything on that line is compile-time only; runtime imports only its output (typed ORM, HTTP routes, gRPC stubs).

- **Compile time** `diag`, `token`, `lexer`, `ast`, `parser`: bytes to a best-effort syntax tree (never panics, depth guard, recovery).
- **Compile time** `naming`, `resolver`, `ir`: multi-pass `[]*ast.File` to `*ir.Schema`, keep-going diagnostics.
- **Compile time** `format`, `breaking`, `compile`, `backend`: formatter, `Change` taxonomy, filename-sorted build, `Backend` interface.
- **Compile time** `dsl/gengrammar` via `tools/gengrammar`: renders `editors/nvim` and `editors/vscode`.
- **Runtime** `container`, `config`, `orm`, adapters: load, resolve, query, close.
- **Tooling** `cmd/zever`, `tools/zever-lsp`: CLI and editor support (LSP is its own module).

## Keep compile input and runtime config apart

The compiler reads schema files and backend flags, never runtime config (env only). Schema errors come from `.zen` files; service errors (adapters, DSNs, secrets) come from `config.FromEnv`.

## Compile, then run against generated output

```sh
zever check schema/todo.zen
zever fmt -l schema/todo.zen
zever compile schema/todo.zen --backend=zenorm,openapi,atlas --out generated
zever db migrate --dry-run --adapter=sqlite schema/todo.zen
go run ./examples/todo/cmd/server -addr :8080
```

`check` validates; `fmt -l` lists unformatted files; `compile` emits ORM, OpenAPI, and DDL into `generated/`; `migrate --dry-run` previews SQL. The server imports `generated/` and resolves through the container, never `dsl` ([Container](https://zenta-dev.github.io/zever/concepts/container/)).

Regenerate with `zever compile`; never hand-edit `generated/`. Entry points are `parser.New(file, src).ParseFile()` then `resolver.Resolve(files)`, or `compile.Compile(files, backends...)`; `compile/testdata/app.zen` is the canonical fixture. After touching `token.Keywords` or `resolver.ScalarTypeNames`, run `make generate` (`go run ./tools/gengrammar`).

## Do not confuse it with schema modules

`zever check-boundaries` checks a different rule: cross-schema-module references, where a relation, RPC return type, or permission resource reaches across `.zen` module directories. The resolver enforces it every compile; `check-boundaries` reports the `Resolve()` diagnostics ([Zen syntax](https://zenta-dev.github.io/zever/reference/zen-syntax/)).

## Design decisions and trade-offs

`dsl` is a top-level module, so Go's `internal/` visibility does not apply; an accidental import fails review. The parser never panics, so failures surface as diagnostics.

## Troubleshooting

<details>
<summary>`go build` fails importing `dsl`</summary>

A runtime package reached the compiler. Drop the import; use `generated/`.
</details>

<details>
<summary>`check-boundaries` reports cross-module references</summary>

A relation or RPC type crosses `.zen` module directories. Move it.
</details>

<details>
<summary>`compile` prints diagnostics but writes no output</summary>

Resolve errors block backends. Fix the `.zen` position; run `zever check`.
</details>

<details>
<summary>The editor misses new keywords after a grammar change</summary>

`token.Keywords` or `resolver.ScalarTypeNames` changed. Run `make generate` and commit `editors/`.
</details>

<details>
<summary>Edits in `generated/` vanish</summary>

Compile overwrites `generated/`. Edit the `.zen` source.
</details>

## Related

- [Resolver and IR](https://zenta-dev.github.io/zever/concepts/resolver-ir/): The frontend pipeline in detail.
- [Backends](https://zenta-dev.github.io/zever/concepts/backends/): The Backend.Generate extension point.
- [Container](https://zenta-dev.github.io/zever/concepts/container/): The runtime resolver.
- [Deployment](https://zenta-dev.github.io/zever/guides/operate/deployment/): Ship generated output without the compiler.
