@mark1russell7/coeval 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/build/index.d.ts +916 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +1856 -0
- package/build/index.js.map +1 -0
- package/package.json +49 -3
- package/src/classify.ts +54 -0
- package/src/context.ts +189 -0
- package/src/deref.ts +290 -0
- package/src/doc.ts +182 -0
- package/src/evaluate.ts +553 -0
- package/src/index.ts +118 -0
- package/src/ladder.ts +141 -0
- package/src/order.ts +111 -0
- package/src/parts.ts +43 -0
- package/src/stdlib.ts +283 -0
- package/src/world.ts +163 -0
- package/README.md +0 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["entryOf","items","makeRootContext"],"sources":["../src/doc.ts","../src/world.ts","../src/ladder.ts","../src/deref.ts","../src/classify.ts","../src/parts.ts","../src/evaluate.ts","../src/stdlib.ts","../src/order.ts","../src/context.ts"],"sourcesContent":["/** A JSON value. */\nexport type Json = null | boolean | number | string | readonly Json[] | { readonly [key: string]: Json };\n\n/** A JSON record. */\nexport type JsonRecord = { readonly [key: string]: Json };\n\n/** One step of a path that is a plain key: a name, or an index of a list. */\nexport type Key = string | number;\n\n/**\n * The type of a document is a reference into the world (the registry of kinds).\n *\n * - A text is a base reference with one key: `\"add\"`.\n * - A list of keys is a base reference with a path: `[\"git\", \"push\"]`.\n * - A document of type `ref` is the same reference, expanded. Its path starts at the root `world`.\n *\n * The kernel resolves a base reference itself. The expanded form is necessary only to attach more to the\n * reference. Thus the chain of types stops at a base reference.\n */\nexport type TypeRef = string | readonly Key[] | { readonly type: \"ref\"; readonly value: readonly Json[] };\n\n/**\n * A typed document: an envelope with a header and a value. The header names the type of the value. The value is\n * not changed by the envelope at any time. Thus any JSON value can have a type: a number, a list, a text or a record.\n */\nexport type Envelope = {\n /** The type: a reference to a kind of the world. */\n readonly type: TypeRef;\n /** The value. */\n readonly value: Json;\n /** The name of a binding. A sequence gives the result of this document to the later steps under this name. */\n readonly name?: string;\n /** The own entries: one evaluator name for each verb. An own entry changes only this document. */\n readonly own?: Readonly<Record<string, string>>;\n};\n\n/** The keys that an envelope can have. */\nexport const ENVELOPE_KEYS = [\"type\", \"value\", \"name\", \"own\"] as const;\n\n/**\n * This function tells if a value is a JSON record (not an array and not null).\n *\n * @param value - The value to examine.\n * @returns `true` for a record.\n */\nexport function isRecord(value: Json | undefined): value is JsonRecord {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * This function reads a field of a record. It reads only the own fields, thus `constructor` is not a field.\n *\n * @param record - The record.\n * @param key - The name of the field.\n * @returns The value of the field, or `undefined` when the record has no such field.\n */\nexport function field(record: JsonRecord, key: string): Json | undefined {\n return Object.hasOwn(record, key) ? record[key] : undefined;\n}\n\n/**\n * This function tells if a value is a key of a path: a text, or a whole number from 0.\n *\n * @param value - The value to examine.\n * @returns `true` for a key.\n */\nexport function isKey(value: Json | undefined): value is Key {\n return typeof value === \"string\" || (typeof value === \"number\" && Number.isInteger(value) && value >= 0);\n}\n\n/**\n * This function tells if a value is a reference to a type. The reference is a text, a list of keys, or a document\n * of type `ref` whose path starts at the root `world`.\n *\n * @param value - The value to examine.\n * @returns `true` for a reference to a type.\n */\nexport function isTypeRef(value: Json | undefined): boolean {\n if (typeof value === \"string\") return value !== \"\";\n if (Array.isArray(value)) return value.length > 0 && (value as readonly Json[]).every(isKey);\n if (!isRecord(value)) return false;\n const path = field(value, \"value\");\n return field(value, \"type\") === \"ref\" && Array.isArray(path) && (path as readonly Json[])[0] === \"world\";\n}\n\n/**\n * This function gives the path of a reference to a type, from the root of the world.\n *\n * @param type - The reference.\n * @returns The keys from the root of the world, or `undefined` for a computed step that has no fixed key.\n */\nexport function typePath(type: TypeRef): readonly Key[] | undefined {\n if (typeof type === \"string\") return [type];\n if (Array.isArray(type)) return type as readonly Key[];\n const steps = (type as { readonly value: readonly Json[] }).value.slice(1);\n return steps.every(isKey) ? (steps as readonly Key[]) : undefined;\n}\n\n/**\n * This function gives the text of a type for a reader: its keys, joined with a dot.\n *\n * @param type - The reference to the type.\n * @returns The text, for example `git.push`.\n */\nexport function typeName(type: TypeRef): string {\n return typePath(type)?.join(\".\") ?? \"(computed)\";\n}\n\n/**\n * This function tells if a value has the form of an envelope. That form is a record with a reference to a type\n * and a `value`. It has no other keys than the keys of an envelope. A contract decides where an envelope is\n * expected. This function only checks the form.\n *\n * @param value - The value to examine.\n * @returns `true` when the value has the form of an envelope.\n */\nexport function isEnvelope(value: Json | undefined): value is JsonRecord & Envelope {\n if (!isRecord(value)) return false;\n if (!isTypeRef(field(value, \"type\")) || !Object.hasOwn(value, \"value\")) return false;\n const name = field(value, \"name\");\n if (name !== undefined && typeof name !== \"string\") return false;\n const own = field(value, \"own\");\n if (own !== undefined && !isRecord(own)) return false;\n return Object.keys(value).every((key) => (ENVELOPE_KEYS as readonly string[]).includes(key));\n}\n\n/**\n * This function makes an envelope.\n *\n * @param type - The reference to the kind.\n * @param value - The value.\n * @param header - The optional name and own entries.\n * @returns The envelope.\n */\nexport function typed(type: TypeRef, value: Json, header: { readonly name?: string; readonly own?: Record<string, string> } = {}): Envelope {\n return { type, value, ...(header.name === undefined ? {} : { name: header.name }), ...(header.own === undefined ? {} : { own: header.own }) };\n}\n\n/**\n * This function makes a reference document: a path from a root of the context.\n *\n * @param path - The steps. The first step is a root: `self`, `names`, `world`, `event` or `caps`.\n * @returns The document of type `ref`.\n */\nexport function ref(...path: readonly Json[]): Envelope {\n return typed(\"ref\", path);\n}\n\n/**\n * This function gives an envelope as a JSON record, for a store or for a view.\n *\n * @param doc - The envelope.\n * @returns The same envelope as JSON.\n */\nexport function toJson(doc: Envelope): JsonRecord {\n return {\n type: doc.type as Json,\n value: doc.value,\n ...(doc.name === undefined ? {} : { name: doc.name }),\n ...(doc.own === undefined ? {} : { own: doc.own }),\n };\n}\n\n/**\n * This function reads an envelope from JSON. A value without the form of an envelope gives `undefined`.\n *\n * @param value - The JSON value.\n * @returns The envelope, or `undefined`.\n */\nexport function fromJson(value: Json | undefined): Envelope | undefined {\n if (!isEnvelope(value)) return undefined;\n const own = field(value, \"own\");\n const ownEntries: Record<string, string> = {};\n if (isRecord(own)) {\n for (const [verb, name] of Object.entries(own)) if (typeof name === \"string\") ownEntries[verb] = name;\n }\n const name = field(value, \"name\");\n return typed(field(value, \"type\") as TypeRef, field(value, \"value\") ?? null, {\n ...(typeof name === \"string\" ? { name } : {}),\n ...(isRecord(own) ? { own: ownEntries } : {}),\n });\n}\n","import { type Envelope, type Json, type Key, type TypeRef, field, isRecord, typePath } from \"./doc.ts\";\n\n/** The two sides of evaluation. `derive` is pure. `run` causes effects in order. */\nexport type Side = \"derive\" | \"run\";\n\n/**\n * Where the parts of a value are. A part is a typed document that the evaluator gets sealed.\n *\n * - `none`: the value is data. It has no parts.\n * - `list`: the value is a list, and each item is a part.\n * - `record`: the value is a record. The named fields are parts, and the other fields are data.\n *\n * `of` is the type of a bare item. An item without an envelope gets this type from its container.\n */\nexport type PartsSpec =\n | { readonly shape: \"none\" }\n | { readonly shape: \"list\"; readonly of?: string }\n | { readonly shape: \"record\"; readonly fields: readonly string[]; readonly of?: string };\n\n/** A kind gives the name of an evaluator for each verb, and the contract of its value. */\nexport interface Kind {\n readonly verbs: Readonly<Record<string, string>>;\n /** Where the parts of the value are. The default is `none`. */\n readonly parts?: PartsSpec;\n /** The side of the kind. A kind of the run side causes effects. The default is `derive`. */\n readonly side?: Side;\n /** One sentence that tells what the kind is. */\n readonly summary?: string;\n}\n\n/** A namespace: a group of entries under one key of the world. */\nexport interface Namespace {\n readonly kinds: Readonly<Record<string, WorldEntry>>;\n}\n\n/** An alias: a reference to another entry of the world. The lookup follows it (collapse). */\nexport type Alias = { readonly type: \"ref\"; readonly value: readonly Json[] };\n\n/** One entry of the world: a kind, a namespace, or an alias. */\nexport type WorldEntry = Kind | Namespace | Alias;\n\n/** A world holds the kinds and the defaults that answer the questions. */\nexport interface World {\n readonly kinds: Readonly<Record<string, WorldEntry>>;\n readonly defaults: Readonly<Record<string, string>>;\n}\n\n/** The result of a lookup of a type in the world. */\nexport type Lookup =\n | { readonly ok: true; readonly kind: Kind; readonly path: readonly Key[]; readonly aliases: number }\n | { readonly ok: false; readonly reason: \"unknown\" | \"cycle\" | \"not-a-kind\" | \"computed\"; readonly path: readonly Key[] };\n\n/**\n * This function tells if an entry of the world is a kind.\n *\n * @param entry - The entry.\n * @returns `true` for a kind.\n */\nexport function isKind(entry: WorldEntry | undefined): entry is Kind {\n return entry !== undefined && Object.hasOwn(entry, \"verbs\");\n}\n\n/**\n * This function tells if an entry of the world is an alias.\n *\n * @param entry - The entry.\n * @returns `true` for an alias.\n */\nexport function isAlias(entry: WorldEntry | undefined): entry is Alias {\n return entry !== undefined && (entry as { type?: unknown }).type === \"ref\" && Array.isArray((entry as { value?: unknown }).value);\n}\n\nfunction entryAt(entries: Readonly<Record<string, WorldEntry>>, key: Key): WorldEntry | undefined {\n const name = String(key);\n return Object.hasOwn(entries, name) ? entries[name] : undefined;\n}\n\n/**\n * This function finds the kind that a type names. It walks the path from the root of the world, one key at a\n * time. An alias on the way is followed until a kind answers (collapse). A cycle of aliases stops the lookup.\n *\n * @param world - The world.\n * @param type - The reference to the type.\n * @returns The kind and the path of the kind after each alias, or the reason of a failure.\n */\nexport function lookupKind(world: World, type: TypeRef): Lookup {\n const start = typePath(type);\n if (start === undefined) return { ok: false, reason: \"computed\", path: [] };\n let path: readonly Key[] = start;\n let aliases = 0;\n for (;;) {\n let entries = world.kinds;\n let entry: WorldEntry | undefined;\n let followed = false;\n for (let index = 0; index < path.length; index += 1) {\n const key = path[index] as Key;\n entry = entryAt(entries, key);\n if (entry === undefined) return { ok: false, reason: \"unknown\", path };\n if (isAlias(entry)) {\n aliases += 1;\n if (aliases > 32) return { ok: false, reason: \"cycle\", path };\n const target = entry.value.slice(1);\n if (entry.value[0] !== \"world\" || !target.every((item) => typeof item === \"string\" || typeof item === \"number\")) {\n return { ok: false, reason: \"not-a-kind\", path };\n }\n path = [...(target as readonly Key[]), ...path.slice(index + 1)];\n followed = true;\n break;\n }\n if (index < path.length - 1) {\n if (isKind(entry)) return { ok: false, reason: \"not-a-kind\", path };\n entries = (entry as Namespace).kinds;\n }\n }\n if (followed) continue;\n if (!isKind(entry)) return { ok: false, reason: \"not-a-kind\", path };\n return { ok: true, kind: entry, path, aliases };\n }\n}\n\n/**\n * This function gives the entries of a world as a JSON record, so that a reference can walk it. A kind is a\n * record with its verbs, an alias is a reference document, and a namespace is a record of its entries.\n *\n * @param entries - The entries.\n * @returns The JSON form.\n */\nexport function entriesAsJson(entries: Readonly<Record<string, WorldEntry>>): Json {\n const out: Record<string, Json> = {};\n for (const [key, entry] of Object.entries(entries)) {\n if (isAlias(entry)) out[key] = { type: \"ref\", value: entry.value };\n else if (isKind(entry)) out[key] = JSON.parse(JSON.stringify(entry)) as Json;\n else out[key] = entriesAsJson((entry as Namespace).kinds);\n }\n return out;\n}\n\n/**\n * This function makes the document of a kind, so that a view can draw it as each other document.\n *\n * @param name - The name of the kind.\n * @param kind - The kind.\n * @returns The document of type `kind`.\n */\nexport function kindDocument(name: string, kind: Kind): Envelope {\n const parts: Json =\n kind.parts === undefined || kind.parts.shape === \"none\"\n ? \"none\"\n : kind.parts.shape === \"list\"\n ? `a list${kind.parts.of === undefined ? \"\" : ` of ${kind.parts.of}`}`\n : `the fields ${kind.parts.fields.join(\", \")}`;\n return { type: \"kind\", value: { name, verbs: { ...kind.verbs }, parts, side: kind.side ?? \"derive\", summary: kind.summary ?? \"\" } };\n}\n\n/**\n * This function tells if a JSON value is the record of a kind.\n *\n * @param value - The value.\n * @returns `true` when the value has verbs.\n */\nexport function looksLikeKind(value: Json | undefined): boolean {\n return isRecord(value) && isRecord(field(value, \"verbs\"));\n}\n","import { type TypeRef, typeName } from \"./doc.ts\";\nimport { type Kind, type World, lookupKind } from \"./world.ts\";\n\nexport type { Kind, Namespace, PartsSpec, Side, World, WorldEntry } from \"./world.ts\";\n\n/** The rungs of the ladder, in the order that a question visits them. */\nexport const RUNGS = [\"own\", \"kind\", \"default\"] as const;\n\n/** One rung of the ladder. */\nexport type Rung = (typeof RUNGS)[number];\n\n/** The place where the ladder found the type. */\nexport type KindSource = \"document\" | \"container\";\n\n/**\n * The outcome of one rung.\n *\n * - `answers`: the rung gives an evaluator.\n * - `no-entry`: the rung has nothing for this verb, thus the question goes to the next rung.\n * - `skipped`: the rung does not apply, because no type is known.\n * - `unknown-kind`: the type is not a kind of the world. The question stops.\n */\nexport type Outcome = \"answers\" | \"no-entry\" | \"skipped\" | \"unknown-kind\";\n\n/** The record of one rung that a question visited. */\nexport interface Step {\n readonly rung: Rung;\n readonly outcome: Outcome;\n /** The evaluator, when the outcome is `answers`. */\n readonly evaluator?: string;\n /** The text of the type, at the kind rung. */\n readonly kind?: string;\n /** The place of the type, at the kind rung. */\n readonly source?: KindSource;\n}\n\n/** The answer to a question. It keeps the record of each rung that the question visited. */\nexport interface Answer {\n readonly verb: string;\n /** The evaluator that answers. A question that stops with an error has no evaluator. */\n readonly evaluator?: string;\n /** The rung that answered. */\n readonly rung?: Rung;\n /** The reason when no rung answers. */\n readonly error?: \"unknown-kind\" | \"no-answer\";\n readonly steps: readonly Step[];\n}\n\n/**\n * The header that the ladder reads: the type and the own entries. An envelope is a header. A bare value has an\n * empty header, and its position can declare its type.\n */\nexport interface Header {\n readonly type?: TypeRef;\n readonly own?: Readonly<Record<string, string>>;\n}\n\n/** The options of a question. */\nexport interface AskOptions {\n /** The type that the position of a bare value declares. The type of an envelope wins. */\n readonly declaredType?: string;\n}\n\nfunction entryOf(verbs: Readonly<Record<string, string>> | undefined, verb: string): string | undefined {\n return verbs !== undefined && Object.hasOwn(verbs, verb) ? verbs[verb] : undefined;\n}\n\n/**\n * This function finds the kind that a type names, and follows each alias. It gives `undefined` for an unknown\n * type.\n *\n * @param world - The world.\n * @param type - The reference to the type.\n * @returns The kind, or `undefined`.\n */\nexport function kindOf(world: World, type: TypeRef): Kind | undefined {\n const found = lookupKind(world, type);\n return found.ok ? found.kind : undefined;\n}\n\n/**\n * This function finds a kind by a text type. It is the same as `kindOf` for a one-key reference.\n *\n * @param world - The world.\n * @param name - The text of the type.\n * @returns The kind, or `undefined`.\n */\nexport function kindNamed(world: World, name: TypeRef): Kind | undefined {\n return kindOf(world, name);\n}\n\n/**\n * This function asks a document a question, and gives the evaluator that answers it.\n *\n * The question visits the rungs in order: the own entry of the envelope, then its kind, then the default of the\n * world. The type comes from the envelope, or else from the type that the position declares. The type is a\n * reference into the world. The ladder does not guess a type from the shape of a value.\n *\n * @param world - The kinds and the defaults.\n * @param doc - The header of the document: an envelope, or `{}` for a bare value.\n * @param verb - The verb of the question, for example `eval` or `view`.\n * @param options - The type that the position declares.\n * @returns The answer, with the record of each rung that the question visited.\n */\nexport function ask(world: World, doc: Header, verb: string, options: AskOptions = {}): Answer {\n const steps: Step[] = [];\n\n const own = entryOf(doc.own, verb);\n if (own !== undefined) {\n steps.push({ rung: \"own\", outcome: \"answers\", evaluator: own });\n return { verb, evaluator: own, rung: \"own\", steps };\n }\n steps.push({ rung: \"own\", outcome: \"no-entry\" });\n\n const type: TypeRef | undefined = doc.type ?? options.declaredType;\n if (type === undefined) {\n steps.push({ rung: \"kind\", outcome: \"skipped\" });\n } else {\n const source: KindSource = doc.type === undefined ? \"container\" : \"document\";\n const name = typeName(type);\n const kind = kindOf(world, type);\n if (kind === undefined) {\n steps.push({ rung: \"kind\", outcome: \"unknown-kind\", kind: name, source });\n return { verb, error: \"unknown-kind\", steps };\n }\n const entry = entryOf(kind.verbs, verb);\n if (entry !== undefined) {\n steps.push({ rung: \"kind\", outcome: \"answers\", evaluator: entry, kind: name, source });\n return { verb, evaluator: entry, rung: \"kind\", steps };\n }\n steps.push({ rung: \"kind\", outcome: \"no-entry\", kind: name, source });\n }\n\n const fallback = entryOf(world.defaults, verb);\n if (fallback !== undefined) {\n steps.push({ rung: \"default\", outcome: \"answers\", evaluator: fallback });\n return { verb, evaluator: fallback, rung: \"default\", steps };\n }\n steps.push({ rung: \"default\", outcome: \"no-entry\" });\n return { verb, error: \"no-answer\", steps };\n}\n","import { type Envelope, type Json, type Key, field, fromJson, isKey, isRecord, typePath } from \"./doc.ts\";\nimport { type World, entriesAsJson, lookupKind } from \"./world.ts\";\n\n/** The brand of a host thing: an object of the host that answers the steps of a path itself. */\nexport const THING: unique symbol = Symbol(\"coeval.thing\");\n\n/**\n * A host thing: an object that answers the steps of a path itself, for example a node of a live tree. It is the\n * own entry of the ladder for the verb `deref`.\n */\nexport interface HostThing {\n readonly [THING]: true;\n /** A short text for a reader, for example `node card`. */\n readonly label: string;\n /**\n * This function answers one step.\n *\n * @param key - The key of the step.\n * @returns What the step reaches, or `undefined`.\n */\n deref(key: Key): Thing | undefined;\n /**\n * This function gives the thing as a value, when a reference ends on it.\n *\n * @returns The value.\n */\n toJson(): Json;\n}\n\n/** Something that a path can reach: a JSON value, or a host thing. */\nexport type Thing = Json | HostThing;\n\n/**\n * This function tells if a thing is a host thing.\n *\n * @param thing - The thing.\n * @returns `true` for a host thing.\n */\nexport function isHostThing(thing: Thing | undefined): thing is HostThing {\n return typeof thing === \"object\" && thing !== null && !Array.isArray(thing) && (thing as Partial<HostThing>)[THING] === true;\n}\n\n/** The roots of a context. Each path starts with one of them. */\nexport const ROOTS = [\"self\", \"names\", \"world\", \"event\", \"caps\"] as const;\n\n/** One root of a context. */\nexport type Root = (typeof ROOTS)[number];\n\n/**\n * The context of a term: a record with five roots. A reference reaches outside its term only through them.\n *\n * - `self`: the node that the term is part of.\n * - `names`: the values that the evaluators around the term bound.\n * - `world`: the registry of kinds.\n * - `event`: the event that started a run.\n * - `caps`: the effects that the term can cause.\n */\nexport interface Context {\n readonly self: Thing;\n readonly names: Readonly<Record<string, Json>>;\n readonly world: Thing;\n readonly event: Thing;\n readonly caps: readonly string[];\n}\n\n/** The code of a `deref` evaluator: it answers one step of a path on a document of its kind. */\nexport type DerefCode = (doc: Envelope, key: Key) => Thing | undefined;\n\n/** The result of a step document: what it reached, or the reason of a failure. */\nexport type WalkResult = { readonly ok: true; readonly thing: Thing } | { readonly ok: false; readonly reason: string };\n\n/** The input of a walker: the code of a step document, for example `nearest`. */\nexport interface WalkInput {\n /** The value of the step document. */\n readonly data: Json;\n /** The thing that the path reached before this step. */\n readonly here: Thing;\n readonly context: Context;\n /**\n * This function answers one step on a thing, through the ladder.\n *\n * @param thing - The thing.\n * @param key - The key.\n * @returns What the step reaches, or `undefined`.\n */\n deref(thing: Thing, key: Key): Thing | undefined;\n}\n\n/** A walker: the code of the verb `step` of a kind of step documents. */\nexport type Walker = (input: WalkInput) => WalkResult;\n\n/** What a resolution needs: the world, and the code of the `deref` evaluators and of the walkers. */\nexport interface Navigator {\n readonly world: World;\n readonly derefs?: Readonly<Record<string, DerefCode>>;\n readonly walkers?: Readonly<Record<string, Walker>>;\n}\n\n/** The way that one hop of a path was answered. */\nexport type HopBy = \"root\" | \"own\" | \"kind\" | \"default\" | \"step\" | \"collapse\";\n\n/** One hop of a path: the step, what it reached, and who answered it. */\nexport interface Hop {\n readonly step: Json;\n readonly thing: Thing;\n readonly by: HopBy;\n}\n\n/** The result of a resolution: what the path reached, with each hop, or an error with the hops before it. */\nexport type Resolution =\n | { readonly ok: true; readonly thing: Thing; readonly hops: readonly Hop[] }\n | { readonly ok: false; readonly code: \"#REF!\" | \"#CYCLE!\" | \"#STEP?\"; readonly reason: string; readonly hops: readonly Hop[] };\n\nfunction entryOf(verbs: Readonly<Record<string, string>> | undefined, verb: string): string | undefined {\n return verbs !== undefined && Object.hasOwn(verbs, verb) ? verbs[verb] : undefined;\n}\n\nfunction plainStep(thing: Json, key: Key): Json | undefined {\n if (Array.isArray(thing)) {\n const index = typeof key === \"number\" ? key : /^\\d+$/.test(key) ? Number(key) : -1;\n return index >= 0 ? (thing as readonly Json[])[index] : undefined;\n }\n if (isRecord(thing) && typeof key === \"string\") return field(thing, key);\n return undefined;\n}\n\n/**\n * This function answers one step of a path on a thing, through the ladder of the verb `deref`. A host thing\n * answers for itself (own). A document asks its own entry, then its kind. The default goes into the value: a field\n * of a record, or an item of a list.\n *\n * @param nav - The world and the code of the evaluators.\n * @param thing - The thing that the path reached.\n * @param key - The key of the step.\n * @returns What the step reaches and the rung that answered, or `undefined`.\n */\nexport function derefStep(nav: Navigator, thing: Thing, key: Key): { readonly thing: Thing; readonly by: HopBy } | undefined {\n if (isHostThing(thing)) {\n const reached = thing.deref(key);\n return reached === undefined ? undefined : { thing: reached, by: \"own\" };\n }\n const envelope = fromJson(thing);\n if (envelope !== undefined) {\n const own = entryOf(envelope.own, \"deref\");\n const ownCode = own === undefined ? undefined : nav.derefs?.[own];\n if (ownCode !== undefined) {\n const reached = ownCode(envelope, key);\n return reached === undefined ? undefined : { thing: reached, by: \"own\" };\n }\n const found = lookupKind(nav.world, envelope.type);\n const name = found.ok ? entryOf(found.kind.verbs, \"deref\") : undefined;\n const code = name === undefined ? undefined : nav.derefs?.[name];\n if (code !== undefined) {\n const reached = code(envelope, key);\n return reached === undefined ? undefined : { thing: reached, by: \"kind\" };\n }\n const reached = plainStep(envelope.value, key);\n return reached === undefined ? undefined : { thing: reached, by: \"default\" };\n }\n const reached = plainStep(thing, key);\n return reached === undefined ? undefined : { thing: reached, by: \"default\" };\n}\n\n/**\n * This function tells if a thing is a reference document: an envelope of the type `ref`.\n *\n * @param thing - The thing.\n * @returns `true` for a reference document.\n */\nexport function isRef(thing: Thing | undefined): thing is Envelope & { readonly value: readonly Json[] } {\n if (thing === undefined || isHostThing(thing)) return false;\n const envelope = fromJson(thing);\n if (envelope === undefined || !Array.isArray(envelope.value)) return false;\n const path = typePath(envelope.type);\n return path !== undefined && path.length === 1 && path[0] === \"ref\";\n}\n\n/**\n * This function makes the thing of the root `world`: the entries of the world as JSON. An alias is a reference\n * document in it, thus a walk through the world follows each alias (collapse).\n *\n * @param world - The world.\n * @returns The thing.\n */\nexport function worldThing(world: World): Json {\n return entriesAsJson(world.kinds);\n}\n\n/**\n * This function makes a context. The world comes from the navigator when the call gives none.\n *\n * @param parts - The roots to set.\n * @returns The context.\n */\nexport function context(parts: Partial<Context> = {}): Context {\n return {\n self: parts.self ?? null,\n names: parts.names ?? {},\n world: parts.world ?? null,\n event: parts.event ?? null,\n caps: parts.caps ?? [],\n };\n}\n\nconst MAX_COLLAPSE = 64;\n\n/**\n * This function resolves a path from a context, and records each hop.\n *\n * The first step is a root of the context. Each later step is a key or a step document. A key goes up the ladder\n * of the verb `deref` on the thing that the path reached. A step document is evaluated by the walker of its kind,\n * with the thing that the path reached. After each hop, a reference document is followed until the path reaches\n * something else (collapse).\n *\n * @param nav - The world and the code of the evaluators.\n * @param ctx - The context.\n * @param path - The steps.\n * @returns What the path reached and each hop, or an error.\n */\nexport function resolve(nav: Navigator, ctx: Context, path: readonly Json[]): Resolution {\n const hops: Hop[] = [];\n let collapses = 0;\n\n const collapse = (thing: Thing): Resolution => {\n let here = thing;\n while (isRef(here)) {\n collapses += 1;\n if (collapses > MAX_COLLAPSE) return { ok: false, code: \"#CYCLE!\", reason: \"The references form a cycle.\", hops };\n const inner = walk(here.value);\n if (!inner.ok) return inner;\n here = inner.thing;\n hops.push({ step: here === null ? null : \"collapse\", thing: here, by: \"collapse\" });\n }\n return { ok: true, thing: here, hops };\n };\n\n const walk = (steps: readonly Json[]): Resolution => {\n const [root, ...rest] = steps;\n if (typeof root !== \"string\" || !(ROOTS as readonly string[]).includes(root)) {\n return { ok: false, code: \"#REF!\", reason: `A path starts with a root: ${ROOTS.join(\", \")}.`, hops };\n }\n let here: Thing = ctx[root as Root] as Thing;\n hops.push({ step: root, thing: here, by: \"root\" });\n const first = collapse(here);\n if (!first.ok) return first;\n here = first.thing;\n for (const step of rest) {\n if (isKey(step)) {\n const reached = derefStep(nav, here, step);\n if (reached === undefined) return { ok: false, code: \"#REF!\", reason: `The step ${String(step)} reaches nothing.`, hops };\n hops.push({ step, thing: reached.thing, by: reached.by });\n here = reached.thing;\n } else {\n const envelope = fromJson(step);\n const found = envelope === undefined ? undefined : lookupKind(nav.world, envelope.type);\n const name = found?.ok === true ? entryOf(found.kind.verbs, \"step\") : undefined;\n const walker = name === undefined ? undefined : nav.walkers?.[name];\n if (envelope === undefined || walker === undefined) {\n return { ok: false, code: \"#STEP?\", reason: \"A step is a key, or a document of a kind with the verb step.\", hops };\n }\n const result = walker({\n data: envelope.value,\n here,\n context: ctx,\n deref: (thing, key) => derefStep(nav, thing, key)?.thing,\n });\n if (!result.ok) return { ok: false, code: \"#REF!\", reason: result.reason, hops };\n hops.push({ step, thing: result.thing, by: \"step\" });\n here = result.thing;\n }\n const next = collapse(here);\n if (!next.ok) return next;\n here = next.thing;\n }\n return { ok: true, thing: here, hops };\n };\n\n if (path.length === 0) return { ok: false, code: \"#REF!\", reason: \"A path has at least one step: its root.\", hops };\n return walk(path);\n}\n\n/**\n * This function gives the value of a thing: the thing itself for JSON, or the value that a host thing gives.\n *\n * @param thing - The thing.\n * @returns The value.\n */\nexport function valueOfThing(thing: Thing): Json {\n return isHostThing(thing) ? thing.toJson() : thing;\n}\n","import { type Envelope, type Json, field, isRecord, typed } from \"./doc.ts\";\n\n/** A shape proposes a kind for each document that has all of its fields. */\nexport interface Shape {\n readonly name: string;\n readonly fields: readonly string[];\n readonly kind: string;\n}\n\n/** The result of a classification. */\nexport interface Classification {\n /** The kind of the one most specific shape. */\n readonly kind?: string;\n /** The names of the most specific shapes. */\n readonly candidates: readonly string[];\n /** `no-match`: no shape applies. `ambiguous`: two or more shapes match equally well. */\n readonly error?: \"no-match\" | \"ambiguous\";\n}\n\nfunction isStrictSuperset(larger: readonly string[], smaller: readonly string[]): boolean {\n return larger.length > smaller.length && smaller.every((name) => larger.includes(name));\n}\n\n/**\n * This function proposes a kind for a value without a type, from the fields that the value has.\n * A shape applies when the value has each field of the shape. The most specific shapes are the ones that\n * no other applicable shape contains. A host uses a classifier when data comes in, and then tags the data.\n * The ladder does not call a classifier.\n *\n * @param shapes - The shapes to examine.\n * @param value - The value without a type.\n * @returns The proposed kind, or an error with the candidates.\n */\nexport function classify(shapes: readonly Shape[], value: Json): Classification {\n const applicable = isRecord(value)\n ? shapes.filter((shape) => shape.fields.every((name) => field(value, name) !== undefined))\n : [];\n const best = applicable.filter((shape) => !applicable.some((other) => isStrictSuperset(other.fields, shape.fields)));\n const candidates = best.map((shape) => shape.name);\n const only = best.length === 1 ? best[0] : undefined;\n if (only !== undefined) return { kind: only.kind, candidates };\n return { candidates, error: best.length === 0 ? \"no-match\" : \"ambiguous\" };\n}\n\n/**\n * This function puts a value in an envelope with a type. The value does not change.\n *\n * @param value - The value.\n * @param kind - The name of the kind.\n * @returns The envelope.\n */\nexport function tag(value: Json, kind: string): Envelope {\n return typed(kind, value);\n}\n","import { type Json, type JsonRecord, field, isRecord } from \"./doc.ts\";\nimport type { PartsSpec } from \"./ladder.ts\";\n\n/** One part of a value: its key, the JSON of the part, and the type that its position declares. */\nexport interface PartSlot {\n readonly key: string;\n readonly item: Json;\n readonly of?: string;\n}\n\n/** The value of a document, split into its data and its parts. */\nexport type Split =\n | { readonly ok: true; readonly data: Json; readonly parts: readonly PartSlot[] }\n | { readonly ok: false; readonly reason: string };\n\n/**\n * This function splits a value into its data and its parts, by the contract of its kind. The evaluator and the\n * view use the same split, thus a picture shows the parts that the evaluation gets.\n *\n * @param spec - The contract of the parts.\n * @param value - The value of the document.\n * @returns The data and the parts, or the reason why the value does not obey the contract.\n */\nexport function splitParts(spec: PartsSpec | undefined, value: Json): Split {\n const of = (slot: { key: string; item: Json }, declared: string | undefined): PartSlot =>\n declared === undefined ? slot : { ...slot, of: declared };\n if (spec === undefined || spec.shape === \"none\") return { ok: true, data: value, parts: [] };\n if (spec.shape === \"list\") {\n if (!Array.isArray(value)) return { ok: false, reason: \"The value must be a list.\" };\n const items: readonly Json[] = value;\n return { ok: true, data: null, parts: items.map((item, index) => of({ key: String(index), item }, spec.of)) };\n }\n if (!isRecord(value)) return { ok: false, reason: \"The value must be a record.\" };\n const record: JsonRecord = value;\n const rest: Record<string, Json> = {};\n for (const [key, item] of Object.entries(record)) if (!spec.fields.includes(key)) rest[key] = item;\n const parts: PartSlot[] = [];\n for (const key of spec.fields) {\n const item = field(record, key);\n if (item !== undefined) parts.push(of({ key, item }, spec.of));\n }\n return { ok: true, data: rest, parts };\n}\n","import { type Envelope, type Json, fromJson, typed, typeName } from \"./doc.ts\";\nimport { splitParts } from \"./parts.ts\";\nimport { ask, kindOf, type Answer } from \"./ladder.ts\";\nimport type { Side } from \"./world.ts\";\nimport {\n type Context,\n type Navigator,\n type Resolution,\n type Thing,\n context as makeRootContext,\n isHostThing,\n resolve,\n worldThing,\n} from \"./deref.ts\";\n\nexport type { Context } from \"./deref.ts\";\n\n/** The code of an error value. */\nexport type ErrorCode =\n | \"#KIND?\"\n | \"#NOEVAL\"\n | \"#PART?\"\n | \"#NAME?\"\n | \"#REF!\"\n | \"#CYCLE!\"\n | \"#STEP?\"\n | \"#VALUE!\"\n | \"#ARGS\"\n | \"#CAP!\"\n | \"#CALC!\"\n | \"#DEPTH!\";\n\n/** An error value: a code and a reason. An evaluation gives an error value, and it does not throw. */\nexport interface EvalError {\n readonly code: ErrorCode;\n readonly reason: string;\n}\n\n/** The result of an evaluation: a value, or an error value. */\nexport type Result = { readonly ok: true; readonly value: Json } | { readonly ok: false; readonly error: EvalError };\n\n/**\n * This function makes a result with a value.\n *\n * @param value - The value.\n * @returns The result.\n */\nexport function ok(value: Json): Result {\n return { ok: true, value };\n}\n\n/**\n * This function makes a result with an error value.\n *\n * @param code - The code of the error.\n * @param reason - One sentence that tells the cause.\n * @returns The result.\n */\nexport function fail(code: ErrorCode, reason: string): Result {\n return { ok: false, error: { code, reason } };\n}\n\n/**\n * This function makes a context with names and capabilities. The other roots are empty, and an evaluation sets\n * the world.\n *\n * @param names - The names and their values.\n * @param caps - The effects that the term can cause.\n * @param self - The node of the term, if it has one.\n * @returns The context.\n */\nexport function makeContext(names: Readonly<Record<string, Json>> = {}, caps: readonly string[] = [], self: Thing = null): Context {\n return makeRootContext({ names, caps, self });\n}\n\n/**\n * A sealed part. An evaluator can read the binding name of a part and evaluate it. It cannot read the value of the\n * part, thus two parts that give the same results can replace each other.\n */\nexport interface Part {\n /** The position of the part in its parent: an index of a list, or a field of a record. */\n readonly key: string;\n /** The binding name from the header of the part. */\n readonly name?: string;\n /**\n * This function evaluates the part. Each call is a new evaluation.\n *\n * @param context - The context for the part. The default is the context of the parent.\n * @returns The result of the part.\n */\n evaluate(context?: Context): Result;\n}\n\n/** The input of an evaluator. */\nexport interface EvalInput {\n /** The text of the type of the document, for example `add` or `math.sum` after its alias. */\n readonly kind: string;\n /** The value of the document without its parts. */\n readonly data: Json;\n /** The parts, in the order of the value. */\n readonly parts: readonly Part[];\n /** The context of the document. */\n readonly context: Context;\n /**\n * This function resolves a path from the context of the document.\n *\n * @param path - The steps. The first step is a root.\n * @returns What the path reached, with each hop.\n */\n resolve(path: readonly Json[]): Resolution;\n /**\n * This function causes an effect. The context must have the capability for the kind of the effect. In a run, an\n * evaluator cannot cause an effect: the host does each effect, thus only a runner can wait for it.\n *\n * @param kind - The kind of the effect, for example `log`.\n * @param payload - The data of the effect.\n * @returns The payload, or the error `#CAP!`.\n */\n effect(kind: string, payload: Json): Result;\n}\n\n/** An evaluator: a function from the input of a document to a result. */\nexport type Evaluator = (input: EvalInput) => Result;\n\n/**\n * The steps of an evaluation that can wait. It yields a promise only when the host makes it wait. A runner takes the\n * result of a part with `yield*`, thus a run goes on at once until an effect waits.\n */\nexport type Steps = Generator<Promise<Result>, Result, Result>;\n\n/** A part for a runner. Its evaluation can wait for the effects in it. */\nexport interface RunPart {\n /** The position of the part in its parent: an index of a list, or a field of a record. */\n readonly key: string;\n /** The binding name from the header of the part. */\n readonly name?: string;\n /**\n * This function evaluates the part. Each call is a new evaluation. Take its result with `yield*`.\n *\n * @param context - The context for the part. The default is the context of the parent.\n * @returns The steps of the evaluation of the part.\n */\n evaluate(context?: Context): Steps;\n}\n\n/** The input of a runner: the input of an evaluator, with parts and effects that can wait. */\nexport interface RunInput {\n /** The text of the type of the document. */\n readonly kind: string;\n /** The value of the document without its parts. */\n readonly data: Json;\n /** The parts, in the order of the value. */\n readonly parts: readonly RunPart[];\n /** The context of the document. */\n readonly context: Context;\n /**\n * This function resolves a path from the context of the document.\n *\n * @param path - The steps. The first step is a root.\n * @returns What the path reached, with each hop.\n */\n resolve(path: readonly Json[]): Resolution;\n /**\n * This function causes an effect. The context must have the capability. In a run, the host does the effect,\n * and the steps wait when the host waits. In an evaluation, the effect gives its payload. Take its result with\n * `yield*`.\n *\n * @param kind - The kind of the effect, for example `log`.\n * @param payload - The data of the effect.\n * @returns The steps that give the result of the host, or an error value.\n */\n effect(kind: string, payload: Json): Steps;\n}\n\n/**\n * A runner: the code of a kind whose parts or effects can wait, as a generator function. The same runner serves an\n * evaluation, which does not wait at any time, and a run, in which the host does each effect.\n */\nexport type Runner = (input: RunInput) => Steps;\n\n/** A machine: a world of kinds, and the code of each evaluator name, of each `deref` and of each walker. */\nexport interface Machine extends Navigator {\n readonly evaluators: Readonly<Record<string, Evaluator>>;\n /** The runners, by evaluator name. A runner wins over an evaluator of the same name. */\n readonly runners?: Readonly<Record<string, Runner>>;\n /** The deepest nesting of evaluations. The default is 200. */\n readonly maxDepth?: number;\n}\n\n/** An effect that an evaluation caused, in the order of the effects. */\nexport interface Effect {\n readonly index: number;\n readonly kind: string;\n readonly payload: Json;\n /** The ID of the trace node that caused the effect. */\n readonly node: number;\n /** The number of events before the effect. The effect comes before the end of its node. */\n readonly at: number;\n}\n\n/** The host side of a run: it does one effect, and gives its result. A throw or a rejection is an error value. */\nexport type Perform = (effect: Effect) => Json | Promise<Json>;\n\n/** The options of a run. */\nexport interface RunOptions {\n /** The host code that does each effect. Without it, an effect gives its payload, as in an evaluation. */\n readonly perform?: Perform;\n /** The type of a bare root value. */\n readonly declaredType?: string;\n}\n\n/**\n * This function tells if the capabilities permit an effect. A capability permits the kind of its name, and each kind\n * in its namespace: `store` permits `store.update`.\n *\n * @param caps - The capabilities of the context.\n * @param kind - The kind of the effect.\n * @returns `true` when one capability permits it.\n */\nexport function permits(caps: readonly string[], kind: string): boolean {\n return caps.some((cap) => cap === kind || kind.startsWith(`${cap}.`));\n}\n\n/** One evaluation in a trace. The children are the evaluations of its parts, in the order that they started. */\nexport interface TraceNode {\n readonly id: number;\n /** The keys from the root document to this document. */\n readonly path: readonly string[];\n /** The document. A bare value has the type that its position declares. */\n readonly doc: Envelope;\n /** `true` when the type came from the container and not from an envelope. */\n readonly declared: boolean;\n /** The answer of the ladder to the verb `eval`. */\n readonly answer: Answer;\n readonly side: Side;\n /** The names that the document could read when its evaluation started. */\n readonly names: readonly string[];\n /** The names and their values when the evaluation started. */\n readonly scope: Readonly<Record<string, Json>>;\n /** The capabilities that the document had when its evaluation started. */\n readonly caps: readonly string[];\n /** A short text for the root `self` when the evaluation started. */\n readonly self: string;\n /** The time of the start. Each start and each end takes one tick. */\n readonly enter: number;\n /** The time of the end. */\n readonly exit: number;\n readonly result: Result;\n readonly children: readonly TraceNode[];\n /** The indices of the effects that this document caused itself. */\n readonly effects: readonly number[];\n}\n\n/** The record of one evaluation of a document. */\nexport interface Run {\n readonly result: Result;\n readonly trace: TraceNode;\n readonly effects: readonly Effect[];\n /** The number of ticks. */\n readonly time: number;\n}\n\ninterface Building {\n id: number;\n path: readonly string[];\n doc: Envelope;\n declared: boolean;\n answer: Answer;\n side: Side;\n names: readonly string[];\n scope: Readonly<Record<string, Json>>;\n caps: readonly string[];\n self: string;\n enter: number;\n exit: number;\n result: Result;\n children: Building[];\n effects: number[];\n}\n\nfunction selfLabel(self: Thing): string {\n if (isHostThing(self)) return self.label;\n return self === null ? \"none\" : JSON.stringify(self).slice(0, 40);\n}\n\nconst NO_ANSWER: Answer = { verb: \"eval\", error: \"no-answer\", steps: [] };\n\n/** The state of one evaluation or run: the machine, the effects and the clock. */\ninterface Session {\n readonly machine: Machine;\n /** `true` in a run: the runners take part, and the host does each effect. */\n readonly running: boolean;\n readonly perform: Perform | undefined;\n readonly effects: Effect[];\n tick: number;\n nextId: number;\n}\n\n/** This function drives steps that cannot wait. */\nfunction drive(steps: Steps): Result {\n const step = steps.next();\n if (step.done === true) return step.value;\n void step.value.catch(() => undefined);\n return fail(\"#CALC!\", \"A part waited, and its parent cannot wait.\");\n}\n\n/** This function drives steps that can wait. The steps before the first wait happen at once, in the call. */\nasync function driveWaiting(steps: Steps): Promise<Result> {\n let step = steps.next();\n while (step.done !== true) {\n let value: Result;\n try {\n value = await step.value;\n } catch (error) {\n step = steps.throw(error);\n continue;\n }\n step = steps.next(value);\n }\n return step.value;\n}\n\nfunction* visit(\n s: Session,\n value: Json,\n path: readonly string[],\n declared: string | undefined,\n ctx: Context,\n parent: Building,\n canWait: boolean,\n): Steps {\n const envelope = fromJson(value);\n const doc: Envelope = envelope ?? typed(declared ?? \"?\", value);\n const node: Building = {\n id: s.nextId,\n path,\n doc,\n declared: envelope === undefined,\n answer: NO_ANSWER,\n side: \"derive\",\n names: Object.keys(ctx.names),\n scope: ctx.names,\n caps: ctx.caps,\n self: selfLabel(ctx.self),\n enter: s.tick,\n exit: s.tick,\n result: fail(\"#NOEVAL\", \"The evaluation did not end.\"),\n children: [],\n effects: [],\n };\n s.nextId += 1;\n s.tick += 1;\n parent.children.push(node);\n const finish = (result: Result): Result => {\n node.result = result;\n node.exit = s.tick;\n s.tick += 1;\n return result;\n };\n\n if (envelope === undefined && declared === undefined) {\n return finish(fail(\"#PART?\", \"The value has no envelope, and its position declares no type.\"));\n }\n const maxDepth = s.machine.maxDepth ?? 200;\n if (path.length > maxDepth) return finish(fail(\"#DEPTH!\", `The nesting is deeper than ${maxDepth} documents.`));\n\n const answer = ask(s.machine.world, envelope ?? {}, \"eval\", declared === undefined ? {} : { declaredType: declared });\n node.answer = answer;\n const kind = kindOf(s.machine.world, doc.type);\n node.side = kind?.side ?? \"derive\";\n if (answer.error === \"unknown-kind\") return finish(fail(\"#KIND?\", `The world has no kind ${typeName(doc.type)}.`));\n const name = answer.evaluator;\n const runners = s.machine.runners ?? {};\n const hasRunner = name !== undefined && Object.hasOwn(runners, name);\n const runner = hasRunner ? runners[name] : undefined;\n const code = name !== undefined && Object.hasOwn(s.machine.evaluators, name) ? s.machine.evaluators[name] : undefined;\n if (name === undefined || (runner === undefined && code === undefined)) {\n return finish(fail(\"#NOEVAL\", `No rung gives an evaluator for ${typeName(doc.type)}.`));\n }\n if (runner !== undefined && s.running && !canWait) {\n return finish(fail(\"#CALC!\", `${typeName(doc.type)} waits for effects, and its parent cannot wait. Give the parent a runner.`));\n }\n\n const split = splitParts(kind?.parts, doc.value);\n if (!split.ok) return finish(fail(\"#VALUE!\", `${split.reason} The kind is ${typeName(doc.type)}.`));\n const slots = split.parts.map((slot) => ({ slot, header: fromJson(slot.item) }));\n const record = (effectKind: string, payload: Json): Result | Effect => {\n if (!permits(ctx.caps, effectKind)) return fail(\"#CAP!\", `The context has no capability for the effect ${effectKind}.`);\n const effect: Effect = { index: s.effects.length, kind: effectKind, payload, node: node.id, at: s.tick };\n s.effects.push(effect);\n node.effects.push(effect.index);\n return effect;\n };\n const kindText = typeName(doc.type);\n const resolveHere = (steps: readonly Json[]): Resolution => resolve(s.machine, ctx, steps);\n\n if (runner !== undefined) {\n const parts: RunPart[] = slots.map(({ slot, header }) => ({\n key: slot.key,\n ...(header?.name === undefined ? {} : { name: header.name }),\n evaluate: (override?: Context) => visit(s, slot.item, [...path, slot.key], slot.of, override ?? ctx, node, true),\n }));\n const input: RunInput = {\n kind: kindText,\n data: split.data,\n parts,\n context: ctx,\n resolve: resolveHere,\n effect: function* (effectKind: string, payload: Json): Steps {\n const made = record(effectKind, payload);\n if (\"ok\" in made) return made;\n if (!s.running || s.perform === undefined) return ok(payload);\n const failed = (error: unknown): Result => fail(\"#CALC!\", `The host failed the effect ${effectKind}: ${String(error)}`);\n let done: Json | Promise<Json>;\n try {\n done = s.perform(made);\n } catch (error) {\n return failed(error);\n }\n if (!(done instanceof Promise)) return ok(done ?? null);\n return yield done.then((result) => ok(result ?? null), failed);\n },\n };\n try {\n return finish(yield* runner(input));\n } catch (error) {\n return finish(fail(\"#CALC!\", `The runner ${name} threw: ${String(error)}`));\n }\n }\n\n const parts: Part[] = slots.map(({ slot, header }) => ({\n key: slot.key,\n ...(header?.name === undefined ? {} : { name: header.name }),\n evaluate: (override?: Context) => drive(visit(s, slot.item, [...path, slot.key], slot.of, override ?? ctx, node, false)),\n }));\n const input: EvalInput = {\n kind: kindText,\n data: split.data,\n parts,\n context: ctx,\n resolve: resolveHere,\n effect: (effectKind: string, payload: Json) => {\n if (s.running) return fail(\"#CALC!\", `The effect ${effectKind} needs a runner: in a run, the host does each effect.`);\n const made = record(effectKind, payload);\n return \"ok\" in made ? made : ok(payload);\n },\n };\n try {\n return finish((code as Evaluator)(input));\n } catch (error) {\n return finish(fail(\"#CALC!\", `The evaluator ${name} threw: ${String(error)}`));\n }\n}\n\nfunction holderNode(): Building {\n return {\n id: -1,\n path: [],\n doc: typed(\"?\", null),\n declared: false,\n answer: NO_ANSWER,\n side: \"derive\",\n names: [],\n scope: {},\n caps: [],\n self: \"none\",\n enter: 0,\n exit: 0,\n result: ok(null),\n children: [],\n effects: [],\n };\n}\n\nfunction rootContext(machine: Machine, context: Context): Context {\n return context.world === null ? { ...context, world: worldThing(machine.world) } : context;\n}\n\nfunction record(s: Session, holder: Building, result: Result): Run {\n const root = holder.children[0];\n if (root === undefined) throw new Error(\"The evaluation made no trace.\");\n return { result, trace: root, effects: s.effects, time: s.tick };\n}\n\n/**\n * This function evaluates a document, and records each evaluation in a trace.\n *\n * The verb `eval` goes up the ladder for each document. The kind of the document tells where its parts are. The\n * evaluator gets each part sealed: it can evaluate the part, and it cannot read its value. A failure gives an error\n * value, and the function does not throw. An effect is recorded in its order, and nothing does it.\n *\n * @param machine - The world and the code of the evaluators.\n * @param doc - The document, as JSON.\n * @param context - The names and the capabilities at the root.\n * @param declaredType - The type of a bare root value.\n * @returns The result, the trace and the effects in their order.\n */\nexport function evaluate(machine: Machine, doc: Json, context: Context = makeContext(), declaredType?: string): Run {\n const s: Session = { machine, running: false, perform: undefined, effects: [], tick: 0, nextId: 0 };\n const holder = holderNode();\n const result = drive(visit(s, doc, [], declaredType, rootContext(machine, context), holder, false));\n return record(s, holder, result);\n}\n\n/**\n * This function runs a document: an evaluation in which the host does each effect. A runner waits for its\n * parts and for its effects, thus a step can read the result of the step before. The part of the run before the\n * first wait happens at once, in the call.\n *\n * @param machine - The world, the evaluators and the runners.\n * @param doc - The document, as JSON.\n * @param context - The names and the capabilities at the root.\n * @param options - The host code that does the effects, and the type of a bare root value.\n * @returns The result, the trace and the effects in their order, when the run ends.\n */\nexport async function run(machine: Machine, doc: Json, context: Context = makeContext(), options: RunOptions = {}): Promise<Run> {\n const s: Session = { machine, running: true, perform: options.perform, effects: [], tick: 0, nextId: 0 };\n const holder = holderNode();\n const result = await driveWaiting(visit(s, doc, [], options.declaredType, rootContext(machine, context), holder, true));\n return record(s, holder, result);\n}\n\n/**\n * This function finds a node of a trace by its path.\n *\n * @param trace - The root of the trace.\n * @param path - The keys from the root.\n * @returns The first evaluation at that path, or `undefined` when the document did not evaluate.\n */\nexport function nodeAt(trace: TraceNode, path: readonly string[]): TraceNode | undefined {\n let node: TraceNode | undefined = trace;\n for (const key of path) {\n node = node?.children.find((child) => child.path[child.path.length - 1] === key);\n if (node === undefined) return undefined;\n }\n return node;\n}\n\n/**\n * This function lists the nodes of a trace in the order of their start.\n *\n * @param trace - The root of the trace.\n * @returns Each node, the root first.\n */\nexport function flatten(trace: TraceNode): readonly TraceNode[] {\n const out: TraceNode[] = [];\n const walk = (node: TraceNode): void => {\n out.push(node);\n node.children.forEach(walk);\n };\n walk(trace);\n return out.sort((a, b) => a.enter - b.enter);\n}\n","import { type Json, type Key, field, isRecord } from \"./doc.ts\";\nimport { type Context, type Evaluator, type Machine, type Part, type Result, type RunPart, type Runner, fail, ok } from \"./evaluate.ts\";\nimport { type HostThing, type Thing, type Walker, THING, isHostThing, valueOfThing } from \"./deref.ts\";\nimport type { World } from \"./ladder.ts\";\n\n/**\n * The world of the examples: small kinds for numbers, lists, conditions, names, sequences and effects.\n * Each kind names an evaluator for `eval` and a view for `view`. The site draws each document with its view.\n */\nexport const STD_WORLD: World = {\n kinds: {\n number: { verbs: { eval: \"data.number\", view: \"view.value\" }, summary: \"A number. Its value is the result.\" },\n text: { verbs: { eval: \"data.text\", view: \"view.value\" }, summary: \"A text. Its value is the result.\" },\n bool: { verbs: { eval: \"data.bool\", view: \"view.value\" }, summary: \"A truth value. Its value is the result.\" },\n add: {\n verbs: { eval: \"math.add\", view: \"view.op\" },\n parts: { shape: \"list\", of: \"number\" },\n summary: \"The sum of its parts. A bare number in its list gets the type number.\",\n },\n multiply: {\n verbs: { eval: \"math.multiply\", view: \"view.op\" },\n parts: { shape: \"list\", of: \"number\" },\n summary: \"The product of its parts.\",\n },\n greater: {\n verbs: { eval: \"math.greater\", view: \"view.op\" },\n parts: { shape: \"list\", of: \"number\" },\n summary: \"True when the first part is greater than the second part.\",\n },\n list: { verbs: { eval: \"list.all\", view: \"view.op\" }, parts: { shape: \"list\" }, summary: \"The results of its parts, as a list.\" },\n if: {\n verbs: { eval: \"control.if\", view: \"view.op\" },\n parts: { shape: \"record\", fields: [\"test\", \"then\", \"else\"] },\n summary: \"It evaluates the test, then only the branch that the test selects.\",\n },\n ref: {\n verbs: { eval: \"ref.resolve\", view: \"view.ref\" },\n summary: \"A path from a root of the context. Each step goes up the ladder of the verb deref.\",\n },\n nearest: {\n verbs: { step: \"walk.nearest\", view: \"view.card\" },\n summary: \"A step of a path: it follows a key again and again, until it reaches a node of a type.\",\n },\n panel: {\n verbs: { eval: \"tree.node\", view: \"view.op\" },\n parts: { shape: \"record\", fields: [\"width\", \"height\", \"children\"], of: \"number\" },\n summary: \"A node of a tree. Its parts see it as self, and each node links to its parent.\",\n },\n box: {\n verbs: { eval: \"tree.node\", view: \"view.op\" },\n parts: { shape: \"record\", fields: [\"width\", \"height\", \"children\"], of: \"number\" },\n summary: \"A node of a tree, as panel. A formula in a box can read the parent of the box.\",\n },\n math: {\n kinds: {\n sum: { type: \"ref\", value: [\"world\", \"add\"] },\n product: { type: \"ref\", value: [\"world\", \"multiply\"] },\n },\n },\n seq: {\n verbs: { eval: \"control.seq\", view: \"view.seq\" },\n parts: { shape: \"list\" },\n summary: \"Its steps, in order. The result of a named step is a name for the later steps.\",\n },\n pure: {\n verbs: { eval: \"control.pure\", view: \"view.op\" },\n parts: { shape: \"list\" },\n summary: \"It evaluates its part without capabilities, thus an effect in it fails.\",\n },\n log: {\n verbs: { eval: \"effect.log\", view: \"view.op\" },\n parts: { shape: \"list\", of: \"text\" },\n side: \"run\",\n summary: \"It writes the result of its part to the log. This is an effect.\",\n },\n write: {\n verbs: { eval: \"effect.write\", view: \"view.op\" },\n parts: { shape: \"record\", fields: [\"value\"] },\n side: \"run\",\n summary: \"It writes the result of its part to the store, at its key. This is an effect.\",\n },\n },\n defaults: { view: \"view.card\" },\n};\n\nfunction isNumber(value: Json): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\n/** This function evaluates each part, collects the errors, and gives the values when no part failed. */\nfunction allValues(results: readonly Result[]): { readonly values: readonly Json[] } | { readonly error: Result } {\n const errors = results.filter((result) => !result.ok);\n const first = errors[0];\n if (first !== undefined && errors.length === 1) return { error: first };\n if (errors.length > 1) return { error: fail(\"#ARGS\", `${errors.length} parts failed.`) };\n return { values: results.map((result) => (result.ok ? result.value : null)) };\n}\n\nfunction numbers(values: readonly Json[], kind: string): readonly number[] | Result {\n const bad = values.findIndex((value) => !isNumber(value));\n if (bad !== -1) return fail(\"#VALUE!\", `Part ${bad} of ${kind} is not a number.`);\n return values.filter(isNumber);\n}\n\nfunction dataOf(type: \"number\" | \"string\" | \"boolean\"): Evaluator {\n return ({ data }) =>\n typeof data === type && (type !== \"number\" || isNumber(data))\n ? ok(data)\n : fail(\"#VALUE!\", `The value must be a ${type === \"string\" ? \"text\" : type}.`);\n}\n\n/** The code of the evaluators of the standard world, by name. */\nexport const STD_EVALUATORS: Readonly<Record<string, Evaluator>> = {\n \"data.number\": dataOf(\"number\"),\n \"data.text\": dataOf(\"string\"),\n \"data.bool\": dataOf(\"boolean\"),\n \"math.add\": ({ parts }) => {\n const all = allValues(parts.map((part) => part.evaluate()));\n if (\"error\" in all) return all.error;\n const values = numbers(all.values, \"add\");\n return Array.isArray(values) ? ok(values.reduce((sum, value) => sum + value, 0)) : (values as Result);\n },\n \"math.multiply\": ({ parts }) => {\n const all = allValues(parts.map((part) => part.evaluate()));\n if (\"error\" in all) return all.error;\n const values = numbers(all.values, \"multiply\");\n return Array.isArray(values) ? ok(values.reduce((product, value) => product * value, 1)) : (values as Result);\n },\n \"math.greater\": ({ parts }) => {\n if (parts.length !== 2) return fail(\"#VALUE!\", \"greater needs exactly two parts.\");\n const all = allValues(parts.map((part) => part.evaluate()));\n if (\"error\" in all) return all.error;\n const values = numbers(all.values, \"greater\");\n if (!Array.isArray(values)) return values as Result;\n const [a, b] = values as readonly number[];\n return ok((a ?? 0) > (b ?? 0));\n },\n \"ref.resolve\": ({ data, resolve }) => {\n if (!Array.isArray(data) || data.length === 0) {\n return fail(\"#VALUE!\", \"The value of ref is a path: a list that starts with a root, for example [\\\"names\\\", \\\"a\\\"].\");\n }\n const path: readonly Json[] = data;\n const found = resolve(path);\n if (found.ok) return ok(valueOfThing(found.thing));\n if (path[0] === \"names\" && found.hops.length === 1) return fail(\"#NAME?\", `The context has no name ${String(path[1])}.`);\n return fail(found.code, found.reason);\n },\n \"tree.node\": (input) => treeNode(input.parts, input.context, input.kind),\n};\n\n/**\n * This function evaluates a node of a tree. The node is a host thing. A step `parent` reaches the node that holds\n * it. A step with the name of a part evaluates that part on demand, one time. Each part sees the node as self.\n */\nfunction treeNode(parts: readonly Part[], context: Context, type: string): Result {\n const memo = new Map<string, Result>();\n const read = (key: string): Result | undefined => {\n const known = memo.get(key);\n if (known !== undefined) return known;\n const part = parts.find((item) => item.key === key);\n if (part === undefined) return undefined;\n const result = part.evaluate({ ...context, self: me });\n memo.set(key, result);\n return result;\n };\n const me: HostThing & { readonly type: string } = {\n [THING]: true,\n type,\n label: `node ${type}`,\n deref(key: Key): Thing | undefined {\n if (key === \"parent\") return context.self;\n if (key === \"type\") return type;\n const result = read(String(key));\n return result?.ok === true ? result.value : undefined;\n },\n toJson(): Json {\n const out: Record<string, Json> = {};\n for (const part of parts) {\n const result = read(part.key);\n out[part.key] = result?.ok === true ? result.value : null;\n }\n return out;\n },\n };\n const out: Record<string, Json> = {};\n for (const part of parts) {\n const result = read(part.key);\n if (result === undefined) continue;\n if (!result.ok) return result;\n out[part.key] = result.value;\n }\n return ok(out);\n}\n\n/**\n * The walker of `nearest`: it follows a key (the default is `parent`) until the node that it reaches has the\n * wanted type. With `self: true`, the node where the walk starts is the first candidate. A node without that key\n * ends the walk with an error.\n */\nconst nearest: Walker = ({ data, here, deref }) => {\n const follow = isRecord(data) && typeof field(data, \"follow\") === \"string\" ? String(field(data, \"follow\")) : \"parent\";\n const wanted = isRecord(data) ? field(data, \"type\") : undefined;\n const fromSelf = isRecord(data) && field(data, \"self\") === true;\n let at: Thing | undefined = here;\n for (let hops = 0; hops < 256; hops += 1) {\n if (hops > 0 || !fromSelf) at = at === undefined || at === null ? undefined : deref(at, follow);\n if (at === undefined || at === null) return { ok: false, reason: `No node of the type ${String(wanted)} is on the way.` };\n const type = isHostThing(at) ? (at as { readonly type?: unknown }).type : undefined;\n if (type === wanted) return { ok: true, thing: at };\n }\n return { ok: false, reason: \"The walk is too long.\" };\n};\n\n/** The walkers of the standard world, by name. */\nexport const STD_WALKERS: Readonly<Record<string, Walker>> = { \"walk.nearest\": nearest };\n\n/** This function evaluates parts one after the other, and stops at the first error. */\nfunction* inOrder(parts: readonly RunPart[]): Generator<Promise<Result>, { readonly values: readonly Json[] } | { readonly error: Result }, Result> {\n const values: Json[] = [];\n for (const part of parts) {\n const result = yield* part.evaluate();\n if (!result.ok) return { error: result };\n values.push(result.value);\n }\n return { values };\n}\n\n/**\n * The runners of the standard world, by name: the kinds that can hold effects. Each one evaluates its parts in\n * order. In a run, an effect ends before the next step starts.\n */\nexport const STD_RUNNERS: Readonly<Record<string, Runner>> = {\n \"control.seq\": function* ({ parts, context }) {\n let names: Record<string, Json> = { ...context.names };\n let last: Json = null;\n for (const part of parts) {\n const result = yield* part.evaluate({ ...context, names });\n if (!result.ok) return result;\n names = { ...names, last: result.value };\n if (part.name !== undefined) names = { ...names, [part.name]: result.value };\n last = result.value;\n }\n return ok(last);\n },\n \"control.pure\": function* ({ parts, context }) {\n const only = parts[0];\n if (only === undefined) return fail(\"#VALUE!\", \"pure needs one part.\");\n return yield* only.evaluate({ ...context, caps: [] });\n },\n \"control.if\": function* ({ parts }) {\n const test = parts.find((part) => part.key === \"test\");\n if (test === undefined) return fail(\"#VALUE!\", \"if needs a test.\");\n const chosen = yield* test.evaluate();\n if (!chosen.ok) return chosen;\n if (typeof chosen.value !== \"boolean\") return fail(\"#VALUE!\", \"The test of if must give a truth value.\");\n const branch = parts.find((part) => part.key === (chosen.value === true ? \"then\" : \"else\"));\n return branch === undefined ? ok(null) : yield* branch.evaluate();\n },\n \"list.all\": function* ({ parts }) {\n const all = yield* inOrder(parts);\n return \"error\" in all ? all.error : ok(all.values);\n },\n \"effect.log\": function* ({ parts, effect }) {\n const all = yield* inOrder(parts);\n if (\"error\" in all) return all.error;\n return yield* effect(\"log\", all.values.length === 1 ? (all.values[0] ?? null) : all.values);\n },\n \"effect.write\": function* ({ parts, data, effect }) {\n const key = isRecord(data) ? field(data, \"key\") : undefined;\n if (typeof key !== \"string\") return fail(\"#VALUE!\", \"write needs a text key.\");\n const value = parts.find((part) => part.key === \"value\");\n if (value === undefined) return fail(\"#VALUE!\", \"write needs a value.\");\n const result = yield* value.evaluate();\n if (!result.ok) return result;\n return yield* effect(\"write\", { key, value: result.value });\n },\n};\n\n/** The machine of the examples: the standard world, its evaluators, its runners and its walkers. */\nexport const STD_MACHINE: Machine = { world: STD_WORLD, evaluators: STD_EVALUATORS, runners: STD_RUNNERS, walkers: STD_WALKERS };\n\n/** The capabilities of the examples at the root: the two effects of the standard world. */\nexport const STD_CAPS: readonly string[] = [\"log\", \"write\"];\n","/** One step of a sequence: its name, the names of the earlier steps that it reads, and if it has an effect. */\nexport interface StepSpec {\n readonly id: string;\n readonly reads: readonly string[];\n readonly effect: boolean;\n}\n\n/** An edge from a step that must come first to a step that must come after it. */\nexport type Edge = readonly [before: string, after: string];\n\n/** A reference that a sequence cannot resolve. */\nexport interface OrderProblem {\n readonly step: string;\n readonly reads: string;\n /** `unknown-name`: no step has this name. `read-before-defined`: the step with this name comes later. */\n readonly problem: \"unknown-name\" | \"read-before-defined\";\n}\n\n/**\n * This function finds the references that a sequence cannot resolve. A step can read only the steps before it.\n *\n * @param steps - The steps, in the written order.\n * @returns One problem for each bad reference, in the written order.\n */\nexport function checkSteps(steps: readonly StepSpec[]): readonly OrderProblem[] {\n const problems: OrderProblem[] = [];\n steps.forEach((step, index) => {\n for (const name of step.reads) {\n const at = steps.findIndex((other) => other.id === name);\n if (at === -1) problems.push({ step: step.id, reads: name, problem: \"unknown-name\" });\n else if (at >= index) problems.push({ step: step.id, reads: name, problem: \"read-before-defined\" });\n }\n });\n return problems;\n}\n\n/**\n * This function gives the data edges: a step comes after each earlier step that it reads.\n *\n * @param steps - The steps, in the written order.\n * @returns The edges. A bad reference gives no edge.\n */\nexport function dataEdges(steps: readonly StepSpec[]): readonly Edge[] {\n const edges: Edge[] = [];\n steps.forEach((step, index) => {\n for (const name of step.reads) {\n const at = steps.findIndex((other) => other.id === name);\n if (at !== -1 && at < index) edges.push([name, step.id]);\n }\n });\n return edges;\n}\n\n/**\n * This function gives the effect edges: each step with an effect comes after the previous step with an effect.\n * Effects keep their written order. Steps without an effect get no effect edge.\n *\n * @param steps - The steps, in the written order.\n * @returns The edges, one for each pair of consecutive effect steps.\n */\nexport function effectEdges(steps: readonly StepSpec[]): readonly Edge[] {\n const edges: Edge[] = [];\n let previous: string | undefined;\n for (const step of steps) {\n if (!step.effect) continue;\n if (previous !== undefined) edges.push([previous, step.id]);\n previous = step.id;\n }\n return edges;\n}\n\n/**\n * This function tells if an order of the steps gives the same meaning as the written order.\n * The order must contain each step one time, and it must obey the data edges and the effect edges.\n *\n * @param steps - The steps, in the written order.\n * @param order - The names of the steps in the order to examine.\n * @returns `true` when the order is permitted.\n */\nexport function isAllowedOrder(steps: readonly StepSpec[], order: readonly string[]): boolean {\n if (order.length !== steps.length) return false;\n if (new Set(order).size !== order.length) return false;\n if (!steps.every((step) => order.includes(step.id))) return false;\n const position = new Map(order.map((id, index) => [id, index] as const));\n return [...dataEdges(steps), ...effectEdges(steps)].every(\n ([before, after]) => (position.get(before) ?? 0) < (position.get(after) ?? 0),\n );\n}\n\n/**\n * This function puts the steps in layers. Each step goes one layer after the last step that it must follow.\n * The steps of one layer do not depend on each other, thus they can run at the same time.\n *\n * @param steps - The steps, in the written order.\n * @returns The layers, first to last. Each layer keeps the written order.\n */\nexport function layers(steps: readonly StepSpec[]): readonly (readonly string[])[] {\n const edges = [...dataEdges(steps), ...effectEdges(steps)];\n const depth = new Map<string, number>();\n for (const step of steps) {\n const before = edges.filter(([, after]) => after === step.id).map(([first]) => depth.get(first) ?? 0);\n depth.set(step.id, before.length === 0 ? 0 : Math.max(...before) + 1);\n }\n const result: string[][] = [];\n for (const step of steps) {\n const at = depth.get(step.id) ?? 0;\n while (result.length <= at) result.push([]);\n result[at]?.push(step.id);\n }\n return result;\n}\n","import type { Envelope } from \"./doc.ts\";\nimport type { Side } from \"./ladder.ts\";\n\n/** The parts of a context. A term can reach outside itself only through these parts. */\nexport const PARTS = [\"names\", \"focus\", \"world\", \"event\", \"caps\"] as const;\n\n/** One part of a context. */\nexport type Part = (typeof PARTS)[number];\n\n/** The description of one part of a context. */\nexport interface PartInfo {\n readonly part: Part;\n readonly title: string;\n /** What a reference through this part reaches. */\n readonly reaches: string;\n /** The direction in which a reference through this part goes. */\n readonly direction: string;\n}\n\n/** The descriptions of the parts, in the order of `PARTS`. */\nexport const PART_INFO: readonly PartInfo[] = [\n {\n part: \"names\",\n title: \"Names\",\n reaches: \"The values that a binding gives: a let, a parameter, or the result of an earlier step.\",\n direction: \"Back, to the place where the program binds the name.\",\n },\n {\n part: \"focus\",\n title: \"Focus\",\n reaches: \"A position in a structure: the node itself, its parent, its children or its siblings.\",\n direction: \"Any direction that a move permits: up, down or to the side.\",\n },\n {\n part: \"world\",\n title: \"World\",\n reaches: \"The stored documents and collections, by an absolute ID or by a query.\",\n direction: \"Out, to the store.\",\n },\n {\n part: \"event\",\n title: \"Event\",\n reaches: \"The trigger of a run: the event and its values.\",\n direction: \"From the past, to the run that the event starts.\",\n },\n {\n part: \"caps\",\n title: \"Capabilities\",\n reaches: \"The effects that a term can cause. A part of the term gets the same set or a smaller set.\",\n direction: \"Down, and only smaller.\",\n },\n];\n\n/**\n * What a construct gives the parts of its body, for one part of the context.\n *\n * - `same`: the parts get the same value.\n * - `extends`: the parts get the value with more names.\n * - `moves`: the parts get a new position.\n * - `narrows`: the parts get a smaller set.\n * - `sets`: the parts get a new value.\n * - `none`: the parts get nothing.\n */\nexport type Give = \"same\" | \"extends\" | \"moves\" | \"narrows\" | \"sets\" | \"none\";\n\n/** How a construct uses one part of the context. */\nexport interface Use {\n readonly reads: boolean;\n readonly gives: Give;\n readonly note: string;\n}\n\n/** A construct of a language, and how it uses each part of the context. */\nexport interface Construct {\n readonly id: string;\n readonly title: string;\n readonly side: Side;\n readonly summary: string;\n readonly example: Envelope;\n readonly uses: Readonly<Record<Part, Use>>;\n}\n\nconst NONE: Use = { reads: false, gives: \"none\", note: \"It does not use this part.\" };\n\n/** Six constructs that show the range of the context. */\nexport const CONSTRUCTS: readonly Construct[] = [\n {\n id: \"formula\",\n title: \"Formula\",\n side: \"derive\",\n summary: \"A pure formula that gives a value at one position of a structure.\",\n example: {\n type: \"formula\",\n value: { let: { gap: 8 }, body: { op: \"add\", args: [{ ref: \"width\", at: \"parent\" }, { var: \"gap\" }] } },\n },\n uses: {\n names: { reads: true, gives: \"extends\", note: \"A let binds names for its body.\" },\n focus: { reads: true, gives: \"moves\", note: \"A move reads the parent. An axis moves the focus to each target.\" },\n world: NONE,\n event: NONE,\n caps: { reads: false, gives: \"none\", note: \"A formula causes no effect, thus its parts get no capability.\" },\n },\n },\n {\n id: \"sequence\",\n title: \"Sequence\",\n side: \"run\",\n summary: \"A list of steps. A step can read the result of each earlier step by its name.\",\n example: {\n type: \"seq\",\n value: [\n { type: \"store.find\", value: { match: { board: \"b1\" } }, name: \"cards\" },\n { type: \"store.patch\", value: { ids: { type: \"ref\", value: \"cards.ids\" }, set: { done: true } } },\n ],\n },\n uses: {\n names: { reads: true, gives: \"extends\", note: \"The result of each step is a name for the later steps.\" },\n focus: NONE,\n world: { reads: true, gives: \"same\", note: \"A step reads and writes the store through a procedure.\" },\n event: { reads: false, gives: \"same\", note: \"The steps get the event of the run without a change.\" },\n caps: { reads: true, gives: \"narrows\", note: \"A nested call gets the same capabilities or fewer.\" },\n },\n },\n {\n id: \"node\",\n title: \"Tree node\",\n side: \"derive\",\n summary: \"A node of a document tree. Its data and its box go down to its children.\",\n example: {\n type: \"node\",\n value: { data: { title: \"Notes\" }, children: [{ type: \"text\", value: { type: \"ref\", value: \"title\" } }] },\n },\n uses: {\n names: { reads: true, gives: \"extends\", note: \"The data of the node becomes a name for its children.\" },\n focus: { reads: true, gives: \"moves\", note: \"Each child becomes the focus of its own part.\" },\n world: { reads: true, gives: \"same\", note: \"A node can show stored documents.\" },\n event: NONE,\n caps: NONE,\n },\n },\n {\n id: \"rule\",\n title: \"Layout rule\",\n side: \"derive\",\n summary: \"A rule that gives the box of a child from the box of its parent.\",\n example: { type: \"rule\", value: { use: \"stack\", with: { gap: 8 } } },\n uses: {\n names: { reads: true, gives: \"none\", note: \"The rule reads its parameters.\" },\n focus: { reads: true, gives: \"none\", note: \"The rule reads the box of the parent and the key of the child.\" },\n world: NONE,\n event: NONE,\n caps: NONE,\n },\n },\n {\n id: \"handler\",\n title: \"Event handler\",\n side: \"run\",\n summary: \"A run that an event starts. It holds a sequence as data until the event comes.\",\n example: {\n type: \"on\",\n value: {\n event: \"click\",\n run: { type: \"seq\", value: [{ type: \"card.toggle\", value: { id: { type: \"ref\", value: \"event.target\" } } }] },\n },\n },\n uses: {\n names: { reads: true, gives: \"same\", note: \"The handler reads the names of its place.\" },\n focus: { reads: true, gives: \"same\", note: \"The handler knows the node that got the event.\" },\n world: { reads: true, gives: \"same\", note: \"The run reads and writes the store.\" },\n event: { reads: true, gives: \"sets\", note: \"The handler gives the event to its run.\" },\n caps: { reads: true, gives: \"narrows\", note: \"The run gets only the capabilities of the handler.\" },\n },\n },\n {\n id: \"query\",\n title: \"Query\",\n side: \"derive\",\n summary: \"A selection of stored documents. A storage adapter decides where it runs.\",\n example: { type: \"query\", value: { collection: \"cards\", match: { board: { type: \"ref\", value: \"board\" } } } },\n uses: {\n names: { reads: true, gives: \"none\", note: \"The query reads its parameters.\" },\n focus: NONE,\n world: { reads: true, gives: \"none\", note: \"The query reads one collection.\" },\n event: NONE,\n caps: NONE,\n },\n },\n];\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,52 @@
|
|
|
1
1
|
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/package",
|
|
2
3
|
"name": "@mark1russell7/coeval",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"description": "coeval: a base for declarative languages. Documents in envelopes, a ladder that finds the evaluator, sealed parts, references as paths from a context, and a traced evaluation.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./build/index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./build/index.d.ts",
|
|
11
|
+
"default": "./build/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"build",
|
|
17
|
+
"src",
|
|
18
|
+
"!src/**/*.test.ts"
|
|
19
|
+
],
|
|
20
|
+
"sideEffects": false,
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/mark1russell7/coeval.git",
|
|
25
|
+
"directory": "packages/core"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"typescript",
|
|
29
|
+
"dsl",
|
|
30
|
+
"declarative",
|
|
31
|
+
"interpreter",
|
|
32
|
+
"language-workbench",
|
|
33
|
+
"coinductive",
|
|
34
|
+
"json"
|
|
35
|
+
],
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@mark1russell7/cue": "github:mark1russell7/cue",
|
|
38
|
+
"@types/node": "^26.6.4",
|
|
39
|
+
"typescript": "^7.0.2",
|
|
40
|
+
"vitest": "^5.0.3"
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build": "tsdown",
|
|
47
|
+
"test": "vitest run",
|
|
48
|
+
"test:watch": "vitest",
|
|
49
|
+
"typecheck": "tsc -p tsconfig.json && tsc -p tsconfig.test.json"
|
|
50
|
+
},
|
|
51
|
+
"types": "./build/index.d.ts"
|
|
6
52
|
}
|
package/src/classify.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type Envelope, type Json, field, isRecord, typed } from "./doc.ts";
|
|
2
|
+
|
|
3
|
+
/** A shape proposes a kind for each document that has all of its fields. */
|
|
4
|
+
export interface Shape {
|
|
5
|
+
readonly name: string;
|
|
6
|
+
readonly fields: readonly string[];
|
|
7
|
+
readonly kind: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** The result of a classification. */
|
|
11
|
+
export interface Classification {
|
|
12
|
+
/** The kind of the one most specific shape. */
|
|
13
|
+
readonly kind?: string;
|
|
14
|
+
/** The names of the most specific shapes. */
|
|
15
|
+
readonly candidates: readonly string[];
|
|
16
|
+
/** `no-match`: no shape applies. `ambiguous`: two or more shapes match equally well. */
|
|
17
|
+
readonly error?: "no-match" | "ambiguous";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function isStrictSuperset(larger: readonly string[], smaller: readonly string[]): boolean {
|
|
21
|
+
return larger.length > smaller.length && smaller.every((name) => larger.includes(name));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* This function proposes a kind for a value without a type, from the fields that the value has.
|
|
26
|
+
* A shape applies when the value has each field of the shape. The most specific shapes are the ones that
|
|
27
|
+
* no other applicable shape contains. A host uses a classifier when data comes in, and then tags the data.
|
|
28
|
+
* The ladder does not call a classifier.
|
|
29
|
+
*
|
|
30
|
+
* @param shapes - The shapes to examine.
|
|
31
|
+
* @param value - The value without a type.
|
|
32
|
+
* @returns The proposed kind, or an error with the candidates.
|
|
33
|
+
*/
|
|
34
|
+
export function classify(shapes: readonly Shape[], value: Json): Classification {
|
|
35
|
+
const applicable = isRecord(value)
|
|
36
|
+
? shapes.filter((shape) => shape.fields.every((name) => field(value, name) !== undefined))
|
|
37
|
+
: [];
|
|
38
|
+
const best = applicable.filter((shape) => !applicable.some((other) => isStrictSuperset(other.fields, shape.fields)));
|
|
39
|
+
const candidates = best.map((shape) => shape.name);
|
|
40
|
+
const only = best.length === 1 ? best[0] : undefined;
|
|
41
|
+
if (only !== undefined) return { kind: only.kind, candidates };
|
|
42
|
+
return { candidates, error: best.length === 0 ? "no-match" : "ambiguous" };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* This function puts a value in an envelope with a type. The value does not change.
|
|
47
|
+
*
|
|
48
|
+
* @param value - The value.
|
|
49
|
+
* @param kind - The name of the kind.
|
|
50
|
+
* @returns The envelope.
|
|
51
|
+
*/
|
|
52
|
+
export function tag(value: Json, kind: string): Envelope {
|
|
53
|
+
return typed(kind, value);
|
|
54
|
+
}
|
package/src/context.ts
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import type { Envelope } from "./doc.ts";
|
|
2
|
+
import type { Side } from "./ladder.ts";
|
|
3
|
+
|
|
4
|
+
/** The parts of a context. A term can reach outside itself only through these parts. */
|
|
5
|
+
export const PARTS = ["names", "focus", "world", "event", "caps"] as const;
|
|
6
|
+
|
|
7
|
+
/** One part of a context. */
|
|
8
|
+
export type Part = (typeof PARTS)[number];
|
|
9
|
+
|
|
10
|
+
/** The description of one part of a context. */
|
|
11
|
+
export interface PartInfo {
|
|
12
|
+
readonly part: Part;
|
|
13
|
+
readonly title: string;
|
|
14
|
+
/** What a reference through this part reaches. */
|
|
15
|
+
readonly reaches: string;
|
|
16
|
+
/** The direction in which a reference through this part goes. */
|
|
17
|
+
readonly direction: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** The descriptions of the parts, in the order of `PARTS`. */
|
|
21
|
+
export const PART_INFO: readonly PartInfo[] = [
|
|
22
|
+
{
|
|
23
|
+
part: "names",
|
|
24
|
+
title: "Names",
|
|
25
|
+
reaches: "The values that a binding gives: a let, a parameter, or the result of an earlier step.",
|
|
26
|
+
direction: "Back, to the place where the program binds the name.",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
part: "focus",
|
|
30
|
+
title: "Focus",
|
|
31
|
+
reaches: "A position in a structure: the node itself, its parent, its children or its siblings.",
|
|
32
|
+
direction: "Any direction that a move permits: up, down or to the side.",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
part: "world",
|
|
36
|
+
title: "World",
|
|
37
|
+
reaches: "The stored documents and collections, by an absolute ID or by a query.",
|
|
38
|
+
direction: "Out, to the store.",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
part: "event",
|
|
42
|
+
title: "Event",
|
|
43
|
+
reaches: "The trigger of a run: the event and its values.",
|
|
44
|
+
direction: "From the past, to the run that the event starts.",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
part: "caps",
|
|
48
|
+
title: "Capabilities",
|
|
49
|
+
reaches: "The effects that a term can cause. A part of the term gets the same set or a smaller set.",
|
|
50
|
+
direction: "Down, and only smaller.",
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* What a construct gives the parts of its body, for one part of the context.
|
|
56
|
+
*
|
|
57
|
+
* - `same`: the parts get the same value.
|
|
58
|
+
* - `extends`: the parts get the value with more names.
|
|
59
|
+
* - `moves`: the parts get a new position.
|
|
60
|
+
* - `narrows`: the parts get a smaller set.
|
|
61
|
+
* - `sets`: the parts get a new value.
|
|
62
|
+
* - `none`: the parts get nothing.
|
|
63
|
+
*/
|
|
64
|
+
export type Give = "same" | "extends" | "moves" | "narrows" | "sets" | "none";
|
|
65
|
+
|
|
66
|
+
/** How a construct uses one part of the context. */
|
|
67
|
+
export interface Use {
|
|
68
|
+
readonly reads: boolean;
|
|
69
|
+
readonly gives: Give;
|
|
70
|
+
readonly note: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** A construct of a language, and how it uses each part of the context. */
|
|
74
|
+
export interface Construct {
|
|
75
|
+
readonly id: string;
|
|
76
|
+
readonly title: string;
|
|
77
|
+
readonly side: Side;
|
|
78
|
+
readonly summary: string;
|
|
79
|
+
readonly example: Envelope;
|
|
80
|
+
readonly uses: Readonly<Record<Part, Use>>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const NONE: Use = { reads: false, gives: "none", note: "It does not use this part." };
|
|
84
|
+
|
|
85
|
+
/** Six constructs that show the range of the context. */
|
|
86
|
+
export const CONSTRUCTS: readonly Construct[] = [
|
|
87
|
+
{
|
|
88
|
+
id: "formula",
|
|
89
|
+
title: "Formula",
|
|
90
|
+
side: "derive",
|
|
91
|
+
summary: "A pure formula that gives a value at one position of a structure.",
|
|
92
|
+
example: {
|
|
93
|
+
type: "formula",
|
|
94
|
+
value: { let: { gap: 8 }, body: { op: "add", args: [{ ref: "width", at: "parent" }, { var: "gap" }] } },
|
|
95
|
+
},
|
|
96
|
+
uses: {
|
|
97
|
+
names: { reads: true, gives: "extends", note: "A let binds names for its body." },
|
|
98
|
+
focus: { reads: true, gives: "moves", note: "A move reads the parent. An axis moves the focus to each target." },
|
|
99
|
+
world: NONE,
|
|
100
|
+
event: NONE,
|
|
101
|
+
caps: { reads: false, gives: "none", note: "A formula causes no effect, thus its parts get no capability." },
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
id: "sequence",
|
|
106
|
+
title: "Sequence",
|
|
107
|
+
side: "run",
|
|
108
|
+
summary: "A list of steps. A step can read the result of each earlier step by its name.",
|
|
109
|
+
example: {
|
|
110
|
+
type: "seq",
|
|
111
|
+
value: [
|
|
112
|
+
{ type: "store.find", value: { match: { board: "b1" } }, name: "cards" },
|
|
113
|
+
{ type: "store.patch", value: { ids: { type: "ref", value: "cards.ids" }, set: { done: true } } },
|
|
114
|
+
],
|
|
115
|
+
},
|
|
116
|
+
uses: {
|
|
117
|
+
names: { reads: true, gives: "extends", note: "The result of each step is a name for the later steps." },
|
|
118
|
+
focus: NONE,
|
|
119
|
+
world: { reads: true, gives: "same", note: "A step reads and writes the store through a procedure." },
|
|
120
|
+
event: { reads: false, gives: "same", note: "The steps get the event of the run without a change." },
|
|
121
|
+
caps: { reads: true, gives: "narrows", note: "A nested call gets the same capabilities or fewer." },
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
id: "node",
|
|
126
|
+
title: "Tree node",
|
|
127
|
+
side: "derive",
|
|
128
|
+
summary: "A node of a document tree. Its data and its box go down to its children.",
|
|
129
|
+
example: {
|
|
130
|
+
type: "node",
|
|
131
|
+
value: { data: { title: "Notes" }, children: [{ type: "text", value: { type: "ref", value: "title" } }] },
|
|
132
|
+
},
|
|
133
|
+
uses: {
|
|
134
|
+
names: { reads: true, gives: "extends", note: "The data of the node becomes a name for its children." },
|
|
135
|
+
focus: { reads: true, gives: "moves", note: "Each child becomes the focus of its own part." },
|
|
136
|
+
world: { reads: true, gives: "same", note: "A node can show stored documents." },
|
|
137
|
+
event: NONE,
|
|
138
|
+
caps: NONE,
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
id: "rule",
|
|
143
|
+
title: "Layout rule",
|
|
144
|
+
side: "derive",
|
|
145
|
+
summary: "A rule that gives the box of a child from the box of its parent.",
|
|
146
|
+
example: { type: "rule", value: { use: "stack", with: { gap: 8 } } },
|
|
147
|
+
uses: {
|
|
148
|
+
names: { reads: true, gives: "none", note: "The rule reads its parameters." },
|
|
149
|
+
focus: { reads: true, gives: "none", note: "The rule reads the box of the parent and the key of the child." },
|
|
150
|
+
world: NONE,
|
|
151
|
+
event: NONE,
|
|
152
|
+
caps: NONE,
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
id: "handler",
|
|
157
|
+
title: "Event handler",
|
|
158
|
+
side: "run",
|
|
159
|
+
summary: "A run that an event starts. It holds a sequence as data until the event comes.",
|
|
160
|
+
example: {
|
|
161
|
+
type: "on",
|
|
162
|
+
value: {
|
|
163
|
+
event: "click",
|
|
164
|
+
run: { type: "seq", value: [{ type: "card.toggle", value: { id: { type: "ref", value: "event.target" } } }] },
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
uses: {
|
|
168
|
+
names: { reads: true, gives: "same", note: "The handler reads the names of its place." },
|
|
169
|
+
focus: { reads: true, gives: "same", note: "The handler knows the node that got the event." },
|
|
170
|
+
world: { reads: true, gives: "same", note: "The run reads and writes the store." },
|
|
171
|
+
event: { reads: true, gives: "sets", note: "The handler gives the event to its run." },
|
|
172
|
+
caps: { reads: true, gives: "narrows", note: "The run gets only the capabilities of the handler." },
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
id: "query",
|
|
177
|
+
title: "Query",
|
|
178
|
+
side: "derive",
|
|
179
|
+
summary: "A selection of stored documents. A storage adapter decides where it runs.",
|
|
180
|
+
example: { type: "query", value: { collection: "cards", match: { board: { type: "ref", value: "board" } } } },
|
|
181
|
+
uses: {
|
|
182
|
+
names: { reads: true, gives: "none", note: "The query reads its parameters." },
|
|
183
|
+
focus: NONE,
|
|
184
|
+
world: { reads: true, gives: "none", note: "The query reads one collection." },
|
|
185
|
+
event: NONE,
|
|
186
|
+
caps: NONE,
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
];
|