# `Hyperlang.SyscallHost`
[🔗](https://github.com/hyperbob-labs/hyperlang/blob/v0.1.0/lib/hyperlang/syscall_host.ex#L1)

The host syscall door contract.

A host (for example the hyperbob_os kernel) supplies guest syscalls as a bound
module rather than an anonymous closure: `{module, state}` where `module`
implements this behaviour and `state` is an opaque host term resolved when
the instance/eval is wired. Every guest syscall is then a single static
remote call:

    module.syscall(state, operation, args)

Return-value convention:

  * any term — the syscall value, passed back to the guest facade as-is
    (Plan 9 C-style values: fd integers, `{n, bytes}`, `0`/`-1`, `nil`)
  * `{:hyperlang_syscall_error, reason}` — a host-side denial or failure,
    surfaced to the runtime as `{:error, reason}`

Closures remain supported for tests and ad-hoc hosts: `normalize/2` wraps a
2- or 3-arity closure in an internal adapter module automatically.

# `op`

```elixir
@type op() :: atom()
```

# `state`

```elixir
@type state() :: term()
```

# `opaque_spawn_args?`
*optional* 

```elixir
@callback opaque_spawn_args?(state()) :: boolean()
```

Return true only when `sys:spawn` argv is an opaque same-program guest transfer.

The runtime still validates the spawned export name, argv list shape, and opts,
but it does not recursively project the argv into public host terms. This is
for scheduler-style hosts such as hyperbob_os, where `spawn` immediately
re-enters the same verified guest program with those args and the host does
not inspect or retain the payload as host data. Ad-hoc function hosts and
bindings that consume argv as ordinary host input must leave this callback
undefined or return false.

# `syscall`

```elixir
@callback syscall(state(), op(), args :: list()) :: term()
```

# `get_state`

```elixir
@spec get_state() :: state()
```

Read the per-eval host state (door-side accessor).

# `normalize`

```elixir
@spec normalize(term(), term()) :: {module(), state()} | nil | :error
```

Normalize a host-supplied `:syscall` option into `{module, state}`.

Accepts a `{module, state}` pair, a 2-arity closure `fun.(op, args)`, or a
3-arity closure `fun.(op, args, host_scope)`; returns `nil` when no host is
attached and `:error` for anything else.

# `put_state`

```elixir
@spec put_state(state()) :: :ok
```

Replace the per-eval host state (door-side accessor).

---

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