# `Schooner.Environment`
[🔗](https://github.com/ausimian/schooner/blob/1.0.0/lib/schooner/environment.ex#L1)

Opaque embedding-friendly environment that bundles a runtime
`Schooner.Env`, an expander `SyntaxEnv`, and a library registry.

An `%Environment{}` is the recommended argument to
`Schooner.eval/2,3` and `Schooner.eval!/2,3` for embedders. It
carries everything needed to evaluate a script in a controlled
surface — which standard libraries are reachable via `(import ...)`,
which host libraries are pre-applied, which named host libraries
are available for the script to import. The struct is opaque:
embedders must not pattern-match on its internals; the public
surface is `new/1`.

## Library composition

  * **Standard libraries** populate the registry from
    `Schooner.Library.standard/0`. The `:standard_libraries`
    option controls which ones are available. Default `:default`
    registers everything Schooner ships with; `:none` ships none;
    a list of canonical names like `[["scheme", "base"], ["scheme",
    "char"]]` ships exactly those.

  * **Named host libraries** (built with
    `Schooner.Host.library/1` and a non-empty `:name`) join the
    registry alongside the standard libraries. The script must
    `(import ...)` them to bring their bindings into scope.
    Sandbox-safe — the embedder controls the menu, the script
    controls which dishes it orders.

  * **Anonymous host libraries** (`name: []`) bypass the registry
    entirely. Their bindings are applied directly to the runtime
    env at construction time, so they are in scope from the
    script's first form without any `(import ...)`. **This is
    sandbox-loosening** — list anonymous libraries deliberately.

  * **`:pre_imports`** auto-apply specific named libraries to the
    runtime env, equivalent to the script having
    `(import (foo bar))` at the top. Useful when the embedder
    always wants a specific surface available without making the
    script repeat the import. Only canonical names are accepted
    at this level (no modifiers); use anonymous libraries or
    script-side `(import (only ...))` for finer control.

## Re-use across evaluations

An `%Environment{}` can be passed to many `Schooner.eval/2,3`
calls. The runtime `env`'s globals slot persists across
evaluations, so a script's top-level `define`s remain visible to
later scripts evaluated against the same environment. This is
the embedding-friendly model for things like rule-loading: load
rule definitions once, evaluate many trigger scripts that call
them.

Each call to `eval` snapshots and restores the per-process
exception / continuation / parameter state, so leftover state
from a script that escaped via `raise` does not bleed into the
next call.

# `t`

```elixir
@opaque t()
```

# `new`

```elixir
@spec new(keyword()) :: t()
```

Build a new `%Environment{}`.

## Options

  * `:standard_libraries` — controls which shipped libraries
    enter the registry. One of:
      * `:default` (default) — every shipped library.
      * `:none` — empty registry.
      * a list of canonical names (e.g.
        `[["scheme", "base"], ["scheme", "char"]]`) or atom
        shortcuts (`:base`, `:char`, `:inexact`, `:complex`,
        `:cxr`, `:write`, `:read`, `:lazy`, `:case_lambda` /
        `:"case-lambda"`).

  * `:libraries` — list of `t:Schooner.Library.t/0` (typically
    built via `Schooner.Host.library/1`). Named libraries join
    the registry; anonymous libraries (`name: []`) have their
    bindings applied directly to the runtime env.

  * `:pre_imports` — list of canonical library names to
    auto-import at construction time. Each name must resolve
    against the assembled registry (standard + named host
    libraries) — a missing name raises
    `Schooner.Library.NotFoundError`.

Returns the constructed `%Environment{}`. Raises `ArgumentError`
for malformed option values.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
