# @ferret/motion: API

the motion language: S-expressions and JSON, waits that suspend across steps, par/race/states, budget, seeded random and snapshots.

39 exports. Generated from the source (`packages/motion/src`), so it matches the code.

## Classes

### Module

*class* · `packages/motion/src/runtime.ts:72`

```ts
class Module
```

- `readonly globals: Env`
- `readonly main: Form[]` — top-level forms that are not definitions: the programs of the file
- `constructor(readonly forms: Form[])`

### MotionBridge

*class* · `packages/motion/src/bridge.ts:42`

```ts
class MotionBridge
```

- `module: Module` — the module that `load` builds; handles started from earlier versions keep theirs
- `constructor(readonly rt: MotionRuntime, private opts: BridgeOptions = {})`
- `define(name: string, sig: Signature, fn: (ctx: Ctx, ...args: any[]) => unknown): this` — Instant: returns a value now. Arguments typed `function` arrive as plain JS functions.
- `lasting(name: string, sig: Signature, fn: LastingFn): this` — Lasting: returns a waitable (`{ done(), result }`) or a promise; the program sleeps on it as on `wait`. A snapshot taken meanwhile resumes after it.
- `action(name: string, sig: Signature, spec: ActionSpec): this` — Action: `start` returns `{ step, stop }`, run every fixed step while the form is active.
- `canCall(name: string): boolean` — may a program call this command? Editing, configuring and loading never; the rest by the allow list.
- `load(text: string, file?: string): Module` — Read definitions into the bridge's module (earlier ones stay).
- `tag(strings: TemplateStringsArray, ...values: unknown[]): MotionSource` — The tagged template: `` motion`(par (stroke left) (stroke right))` ``. Numbers, strings, symbols, lists and booleans are printed in.
- `run(program: string | MotionSource | Form | unknown, params: Record<string, unknown> = {}, opts: { owner?: boolean } = {}): Program` — Start a program from text, a tree, a template result or JSON; `params` are the program's parameters.
- `get(name: string): (...args: unknown[]) => Program` — A `defmotion` as a TypeScript function: `get('stroke')(sym('left'), { power: 700 })` starts it and returns the handle.
- `parse(text: string, file?: string): Form[]`
- `print(f: Form): string`
- `toJson(f: Form): unknown`
- `fromJson(j: unknown): Form`
- `js(v: Value): unknown` — A language value as plain JS: symbols are their names, a lambda is a function that runs to the end (it must not wait).

### MotionError

*class* · `packages/motion/src/reader.ts:26`

```ts
class MotionError extends Error
```

An error with the place in the source: parse errors name the file, line and column; run-time errors name the form.

- `constructor(message: string, readonly pos?: Pos, readonly form?: string)`

### MotionRuntime

*class* · `packages/motion/src/runtime.ts:164`

```ts
class MotionRuntime
```

- `time: number`
- `readonly seed: number`
- `readonly budget: number`
- `readonly fns: Map<string, InstantFn>`
- `readonly actions: Map<string, ActionSpec>`
- `readonly macros: Map<string, (form: Form[]) => Form>` — forms a package rewrites into core forms when a file is loaded (`over-angle` becomes a loop of `wait-until` and `while`)
- `readonly programs: Map<number, Program>`
- `readonly sigs: Map<string, Signature>` — signatures of functions defined from code (`MotionBridge`): arity and literal types are checked at load
- `constructor(opts: MotionOptions = {})`
- `define(name: string, fn: InstantFn): this` — a function that returns a value now: a sensor, a calculation; usable in conditions and arguments
- `macro(name: string, fn: (form: Form[]) => Form): this` — a form rewritten into core forms at load: the rewrite sees the unexpanded arguments, and its result is expanded again
- `expand(f: Form): Form`
- `action(name: string, spec: ActionSpec): this` — an action that lasts while its form is active (a force, a motor)
- `on(event: string, fn: (payload: any) => void): () => void` — events of the runtime for a host: `motion:error`, `motion:done`, `motion:stop`, and whatever programs `emit`
- `emitHost(event: string, payload: unknown)`
- `load(source: string | Form[] | unknown, file?: string): Module` — Read a file of definitions (`defmotion`, `defn`) and programs; every call and its arguments are checked here, not in the middle of a game.
- `validate(mod: Module, program: string | Form | unknown, params: string[] = []): void` — check a program against a module without starting it (names, arity, keywords, states): throws with file:line:col
- `run(mod: Module, program: string | Form | unknown, params: Record<string, Value> = {}, opts: { owner?: boolean } = {}): Program` — Start a program: a form of the module (or text, or JSON) with parameters; it runs from the next `tick`.
- `spawn(p: Program, parent: Thread | null, ctl: Ctl): Thread`
- `kill(p: Program, th: Thread): void`
- `tick(dt: number): void` — One fixed step for every program.
- `deliverTo(p: Program, name: string, payload: Value): void`
- `deliver(name: string, payload: Value = null, only?: Program): void` — An event from the outside (a game, the physics): the threads that wait for it see it on the next step.
- `evalInstant(form: Form, env: Env, ctx: Ctx): Value`
- `snapshot(p: Program): unknown`
- `restore(snap: any): Program`
- `internals()`
- `nextProgramId(): number`
- `setNextProgramId(n: number)`
- `makeProgram(mod: Module, root: Form, params: Record<string, Value>, id: number, seed: number): Program`
- `statesSpecOf(f: Form[])`
- `callClosure(c: Closure, args: Value[]): Value` — Call a lambda or a `defn` from code, to the end (it must not wait); the arguments are plain values.
- `get isClosure()`
- `get isMotionVal()`

### Program

*class* · `packages/motion/src/runtime.ts:88`

```ts
class Program
```

A running program: the handle a host or a game holds.

- `status: ProgramStatus`
- `error?: MotionError`
- `time: number`
- `params: Record<string, Value>`
- `bb: Record<string, Value>`
- `triggers: Set<string>`
- `rng: number`
- `threads: Thread[]`
- `nextThread: number`
- `left: number`
- `readonly done: Promise<Value>` — resolves with the program's value when it ends, or rejects with its error
- `result: Value`
- `constructor(readonly rt: MotionRuntime, readonly id: number, readonly module: Module, readonly root: Form, params: Record<string, Value>, seed: number)`
- `stop(): void`
- `pause(): void`
- `resume(): void`
- `set(param: string, value: Value): void`
- `trigger(name: string): void`
- `on(event: string, fn: (payload: Value) => void): () => void`
- `state()` — what each thread waits for, and the params, for the inspector and `motion.state`
- `snapshot()`
- `emitLocal(name: string, payload: Value)`
- `killAll()`
- `fail(e: unknown)`
- `end(v: Value)`

### Sym

*class* · `packages/motion/src/reader.ts:9`

```ts
class Sym
```

The reader of the motion language: S-expressions in text, and the same tree as a JSON array. No Babylon, no physics.

A form is a number, `true` / `false`, `null` (nil), a string, a symbol (`Sym`), a list (a JS array) or a condition object (the animation
graph's `{ param, op, value }` vocabulary, only in JSON or written inline as `{...}`). In JSON a symbol or keyword is a plain string
(`"oarlock-left"`, `":max-torque"`), a string literal is `{ "s": "text" }`, so `(force oarlock-left forward 600)` is
`["force", "oarlock-left", "forward", 600]` and `(emit "stroke" side)` is `["emit", {"s": "stroke"}, "side"]`.

- `static of(name: string): Sym`
- `get isKeyword(): boolean`
- `toString()`

### Thread

*class* · `packages/motion/src/runtime.ts:58`

```ts
class Thread
```

- `stack: Frame[]`
- `ctl: Ctl`
- `wait: Wait | null`
- `status: Status`
- `value: Value`
- `kids: Thread[]`
- `daemons: Array<{ thread: Thread; depth: number }>`
- `stateT0: number`
- `constructor(readonly id: number, readonly parent: Thread | null)`

## Functions

### brief

*function* · `packages/motion/src/reader.ts:151`

```ts
function brief(f: unknown, max = 80): string
```

A short text of a form for error messages.

### fromJson

*function* · `packages/motion/src/reader.ts:137`

```ts
function fromJson(j: unknown): Form
```

Back from JSON; `file` names the source for errors (a JSON program has no lines).

### netPrograms

*function* · `packages/motion/src/net.ts:18`

```ts
function netPrograms(rt: MotionRuntime, net: MotionNetLike, onAdopt: (name: string, program: Program, from: string) => void): MotionHandover
```

### parse

*function* · `packages/motion/src/reader.ts:52`

```ts
function parse(src: string, file?: string): Form[]
```

Read the text of a program: a list of top-level forms.

### parseOne

*function* · `packages/motion/src/reader.ts:111`

```ts
function parseOne(src: string, file?: string): Form
```

Read exactly one form.

### posOf

*function* · `packages/motion/src/reader.ts:23`

```ts
function posOf: (f: unknown) => Pos | undefined
```

### print

*function* · `packages/motion/src/reader.ts:117`

```ts
function print(f: Form): string
```

### toJson

*function* · `packages/motion/src/reader.ts:129`

```ts
function toJson(f: Form): unknown
```

The JSON array form of a tree (one to one with the text).

## Interfaces

### ActionSpec

*interface* · `packages/motion/src/runtime.ts:31`

```ts
interface ActionSpec
```

- `start(ctx: Ctx, args: Value[]): HoldHandle | void` — called once when an action form starts; the handle's `step` runs every step with the arguments evaluated again

### BridgeOptions

*interface* · `packages/motion/src/bridge.ts:20`

```ts
interface BridgeOptions
```

- `commands?: CommandRunner`
- `allow?: string[]` — exact names or prefixes ending in "." that programs may call through `(cmd ...)` (default `DEFAULT_ALLOW`)

### Closure

*interface* · `packages/motion/src/runtime.ts:16`

```ts
interface Closure
```

- `$: 'fn'`
- `form: Form[]`
- `env: Env`

### CommandRunner

*interface* · `packages/motion/src/bridge.ts:13`

```ts
interface CommandRunner
```

- `execute(name: string, args?: unknown): Promise<unknown> | unknown`

### Ctx

*interface* · `packages/motion/src/runtime.ts:21`

```ts
interface Ctx
```

- `rt: MotionRuntime`
- `program: Program`
- `thread: Thread`
- `env: Env`
- `age: number` — seconds since the action that is being read started (the clock of `half-sine` and the like); 0 outside an action
- `scale: number` — 0..1 while a `ramp` is rising, else 1
- `dt: number`

### Env

*interface* · `packages/motion/src/runtime.ts:15`

```ts
interface Env
```

- `vars: Map<string, Value>`
- `parent: Env | null`

### HoldHandle

*interface* · `packages/motion/src/runtime.ts:30`

```ts
interface HoldHandle
```

- `step?(args: Value[], ctx: Ctx): void`
- `stop?(): void`

### MotionHandover

*interface* · `packages/motion/src/net.ts:13`

```ts
interface MotionHandover
```

- `handOver(name: string, program: Program, peer: string): void` — stop `program` here and send its snapshot to `peer`, who runs it on from the same point
- `dispose(): void`

### MotionNetLike

*interface* · `packages/motion/src/net.ts:8`

```ts
interface MotionNetLike
```

Programs over the net. A program that acts on a body runs only on the machine that owns the body. When the
ownership moves (a player takes the wheel, the owner leaves), the old owner hands the program over as a snapshot and the new owner
continues it exactly where it was, as long as the same actions are defined there. Duck-typed on `NetService`.

- `readonly id: string`
- `send(name: string, data: unknown): void`
- `on(name: string, fn: (data: any, from: string) => void): () => void`

### MotionOptions

*interface* · `packages/motion/src/runtime.ts:157`

```ts
interface MotionOptions
```

- `seed?: number` — the world seed: with the program id it seeds `random`
- `budget?: number` — reductions per thread and step before a loop that never waits is stopped (default 10000)

### MotionSource

*interface* · `packages/motion/src/bridge.ts:27`

```ts
interface MotionSource
```

A program written in code: the text and the tree.

- `readonly text: string`
- `readonly form: Form`

### MotionVal

*interface* · `packages/motion/src/runtime.ts:17`

```ts
interface MotionVal
```

- `$: 'motion'`
- `form: Form[]`
- `env: Env`

### Pos

*interface* · `packages/motion/src/reader.ts:21`

```ts
interface Pos
```

- `line: number`
- `col: number`
- `file?: string`

### Signature

*interface* · `packages/motion/src/runtime.ts:147`

```ts
interface Signature
```

- `args: SigType[]` — argument types; the first `min` are required (default all)
- `min?: number`
- `rest?: SigType` — every argument after `args` has this type
- `returns?: SigType`
- `where?: 'everywhere' | 'owner'` — `owner`: it reads something local (input, the camera, a UI); a program that is not owner-run may not use it

### Waitable

*interface* · `packages/motion/src/bridge.ts:11`

```ts
interface Waitable
```

Code and the language, both ways. Functions from code come in three kinds: **instant** (a value now, usable in
conditions), **lasting** (a waitable the program sleeps on, like `wait`) and **action** (`step` every fixed step while its form is active,
`stop` when it ends). Every function declares a signature, checked when the program loads and when it is called, and where it may run
(`everywhere` or `owner`). Programs come back the other way as handles and as TypeScript functions, a tagged template writes them inline,
and a lambda handed to a function arrives as a plain JS function.

- `done(): boolean`
- `result?: unknown`

## Types

### CondObj

*type* · `packages/motion/src/reader.ts:18`

```ts
type CondObj = { [k: string]: unknown }
```

### Form

*type* · `packages/motion/src/reader.ts:19`

```ts
type Form = number | boolean | null | string | Sym | Form[] | CondObj
```

### InstantFn

*type* · `packages/motion/src/runtime.ts:29`

```ts
type InstantFn = (ctx: Ctx, ...args: Value[]) => Value
```

### LastingFn

*type* · `packages/motion/src/bridge.ts:12`

```ts
type LastingFn = (ctx: Ctx, ...args: any[]) => Waitable | Promise<unknown>
```

### ProgramStatus

*type* · `packages/motion/src/runtime.ts:70`

```ts
type ProgramStatus = 'running' | 'paused' | 'done' | 'error' | 'stopped'
```

### SigType

*type* · `packages/motion/src/runtime.ts:146`

```ts
type SigType = 'number' | 'boolean' | 'string' | 'symbol' | 'vec3' | 'list' | 'function' | 'any'
```

Types a function signature can name (checked when the program loads for literals, and when the function is called for values).

### Value

*type* · `packages/motion/src/runtime.ts:14`

```ts
type Value = number | boolean | null | string | Sym | Value[] | Closure | MotionVal
```

The evaluator of the motion language. A program runs for many fixed steps, so it is a stack machine
of plain data, not a recursive interpreter:
  - a *thread* has a stack of frames (`seq`, `repeat`, `loop`) and at most one wait (time, a condition, an event, a hold, its children);
  - `par`, `race`, `while`, `guard`, `for`, `on` and `states` start child threads, so killing a form kills what it started;
  - an action (`force` ...) is a *hold*: the thread waits on it for ever, its arguments are read again every step, and when something kills
    the thread (`race`, `for`, `while`, a guard) the action stops;
  - conditions, arguments, `defn` and lambdas are evaluated *instantly* by a recursive evaluator: they cannot wait;
  - one budget of reductions per thread and step stops a loop that never waits; the clock is the runtime's own (`tick(dt)`), the random
    numbers are seeded: the same program and the same inputs give the same run, and a snapshot continues it exactly.

## Constants

### DEFAULT_ALLOW

*const* · `packages/motion/src/bridge.ts:16`

```ts
const DEFAULT_ALLOW: string[]
```

Commands a level program may call: run-time commands of the physics packages; the game can replace this list.

### sym

*const* · `packages/motion/src/reader.ts:16`

```ts
const sym: (name: string) => Sym
```

