Logo Mibo

Doc Module

Document resolution: the resolved `Item` tree a front-end's `Node` tree becomes. Layout lives in properties (the style cascade); paint lives in bodies (`Op` data, interpreted at render time — the document text produces no closures of its own beyond one interpreter wrapper per element). Geometry rides the framework's own nouns (`CellPoint`, `CellSize`, `CellRect`, `Align`, `Track`).

Types

Type Description

Element<'T>

One resolvable element of the document tree: the paint body, the merged style, and the container's declared tracks and area template. Carries a paint closure, so it never takes structural equality.

ElementDecl<'T>

One element declared by the game: a name, an optional intrinsic size, and a body of operations. Variations are separate declarations (six corridor directions are six declarations from one F# builder); there are no parameters.

Item<'T>

One resolved item of the document tree. `Name` selects the style rules; `Element` paints the body; `Cols`, `Rows` and `Areas` are the container's declared tracks and area template. Carries a paint closure, so it never takes structural equality.

Kernel<'T>

A per-cell kernel, referenced from a document by name through `generate`. Gen2 generates 2D cells.

Op<'T>

A paint statement as data. The interpreter runs it at render time. Closed by design — the library owns statement semantics, and every statement means the same thing in every game. Consumers extend through elements and words, not through new cases. Geometry is box-local: `FillRect` covers a local rect, `Set` places a local point (or, with `at` absent, places one cell by the two aligns — the `set c` anchor form), `Border` outlines a local rect (absent rect: the whole box), `Generate` runs a kernel over a local rect (absent area: the whole box).

Pack

How a container places its children: stacked children (default), flow tracks, or seeded scatter.

Style

Merged layout properties. Absent means inherit. Two halves: where and how big the element itself is inside its parent (Size, At, Col, Row, Span, Area, PlaceH, PlaceV), and how it places its own children (Pack, Gap, Pad, Seed). Layout only — paint stays in bodies.

Surface<'T>

The game's whole say: cell words, kernels, and its element library. Constructed once, read per build — hence the frozen dictionaries, the fastest read-side dictionary in the BCL.

Functions and values

Function or value Description

applyProp (src, n, s, p)

Full Usage: applyProp (src, n, s, p)

Parameters:
Returns: Result<Style, string>

Applies one layout property (`w=`, `x=`, `col=`, `pack=`, `hplace=`, `seed=`, ...) on top of a style. A value of the wrong shape or an unknown property name is a positioned error.

src : string
n : Node
s : Style
p : Prop
Returns: Result<Style, string>

areasOf (src, n)

Full Usage: areasOf (src, n)

Parameters:
    src : string
    n : Node

Returns: Result<string[][] voption, string>

Resolves one area template — `areas="road woods; road lake"` — into its rows of names. Rows split on `;`, names on spaces and tabs. A row with no name is an authoring slip, not an empty row: it would shift every row below it in the template.

src : string
n : Node
Returns: Result<string[][] voption, string>

at (src, n)

Full Usage: at (src, n)

Parameters:
    src : string
    n : Node

Returns: string

The positioned half of an error message; XML nodes carry Position -1 (that front-end tracks no positions), so the message names the element only.

src : string
n : Node
Returns: string

axisWord w

Full Usage: axisWord w

Parameters:
    w : string

Returns: Align voption

Reads one align word — `start`, `center`, `end`, `stretch` — into its `Align`; anything else is `ValueNone`.

w : string
Returns: Align voption

collectStyles (src, roots)

Full Usage: collectStyles (src, roots)

Parameters:
Returns: Result<Dictionary<string, Style>, string>

Collects `style name ...` rules — the name by word argument (KDL) or by the `name` property (XML). Later rules win per property; a bad property fails the build with its position. Like the template collector, a declaration is a leaf: rules do not nest. The `name` property names the rule; it is a key, not a style, so it is dropped before the properties are applied. A KDL rule states its name as a word argument and never carries the property.

src : string
roots : ImmutableArray<Node>
Returns: Result<Dictionary<string, Style>, string>

collectTemplates (surface, src, roots)

Full Usage: collectTemplates (surface, src, roots)

Parameters:
Returns: Result<Dictionary<string, ElementDecl<'T>>, string>
Type parameters: 'T

Collects `element name { ... }` templates from the whole tree. The definition's `w=`/`h=` state its extent; other properties are errors. The body resolves like any statement list.

surface : Surface<'T>
src : string
roots : ImmutableArray<Node>
Returns: Result<Dictionary<string, ElementDecl<'T>>, string>

csOf v

Full Usage: csOf v

Parameters:
    v : (int * int) voption

Returns: int
Modifiers: inline

The column span of a `colspan`/`rowspan` pair, or 1 when absent — a half-stated span merges field-wise, and one track is the default.

v : (int * int) voption
Returns: int

dimsOf (src, n)

Full Usage: dimsOf (src, n)

Parameters:
    src : string
    n : Node

Returns: Result<CellSize, string>

Reads and validates the map node's dimensions: `w=`/`h=` properties (the XML channel), positional args (the KDL channel), or one of each. A named dimension claims its slot, so `map 36 h=20` reads 36 across and 20 down instead of failing on a mixed document. A doubled dimension, leftover args, and zero or negative dimensions fail with a position.

src : string
n : Node
Returns: Result<CellSize, string>

emptyStyle

Full Usage: emptyStyle

Returns: Style

The solver's defaults: no size, no placement, no pack, no gap. Every cascade starts here, so an absent property means "inherit".

Returns: Style

expandNodes (src, nodes)

Full Usage: expandNodes (src, nodes)

Parameters:
Returns: Result<Node[], string>

`repeat n` duplicates its children, nested repeats included. The count is read by name (`count=`) or positionally. Two caps hold, a per-`repeat` count cap and a 100000-node cap on the expansion's total output — nested repeats multiply, so `repeat 100000 { repeat 100000 { x } }` fails on the running total instead of looping until memory stops. Returns an array; every consumer iterates.

src : string
nodes : ImmutableArray<Node>
Returns: Result<Node[], string>

findMapNode nodes

Full Usage: findMapNode nodes

Parameters:
Returns: Node voption

Locates the document's map container. Its dimensions ride positional args (`map 36 20`) or the `w=`/`h=` properties (`map w="36" h="20"`).

nodes : ImmutableArray<Node>
Returns: Node voption

gapXOf v

Full Usage: gapXOf v

Parameters:
Returns: int
Modifiers: inline

The horizontal half of a `CellSize` gap pair, or 0 when absent.

v : CellSize voption
Returns: int

gapYOf v

Full Usage: gapYOf v

Parameters:
Returns: int
Modifiers: inline

The vertical half of a `CellSize` gap pair, or 0 when absent.

v : CellSize voption
Returns: int

hOf v

Full Usage: hOf v

Parameters:
Returns: int
Modifiers: inline

The `H` of a size, or 0 when absent.

v : CellSize voption
Returns: int

interpret (surface, box, op)

Full Usage: interpret (surface, box, op)

Parameters:
Type parameters: 'T

Runs one statement's paint into `box`.

surface : Surface<'T>
box : GridSection2D<'T>
op : Op<'T>

isListProp name

Full Usage: isListProp name

Parameters:
    name : string

Returns: bool

The three list properties a container states for its own children. They are the container's own channel: they never cascade, and a `style` rule that states one fails.

name : string
Returns: bool

isOpKind kind

Full Usage: isOpKind kind

Parameters:
    kind : string

Returns: bool

Whether the node kind is a paint statement (`fill`, `fillRect`, `set`, `border`, `rect`, `generate`). Everything else in a body is a child container or a declaration node.

kind : string
Returns: bool

layerNameOf (src, n)

Full Usage: layerNameOf (src, n)

Parameters:
    src : string
    n : Node

Returns: Result<string, string>

Reads a layer container's single name: a word argument in KDL (`layer ground { ... }`), the `name` property in XML (``). A layer carries nothing else, so any other argument or property fails with its position.

src : string
n : Node
Returns: Result<string, string>

measure (element, available)

Full Usage: measure (element, available)

Parameters:
Returns: CellSize
Type parameters: 'T

Scratch-grid run, then a scan for the covered area — the general measurement for bodies the op pass cannot see (game-declared elements with custom paint). `available` bounds the scratch grid, so greedy bodies report the available size, not an unbounded one. The resolver's op-derived extents cover the document path; this runs only for `Element<'T>` values a game builds by hand.

element : Element<'T>
available : CellSize
Returns: CellSize

measureOps surface body

Full Usage: measureOps surface body

Parameters:
Returns: CellSize voption
Type parameters: 'T

Derives an element's extent from its body's own geometry: each statement contributes its furthest cell, and any box-relative statement (a whole-box fill, border, or generate) marks the body greedy — its size is whatever the container assigns. A `set` that places a spanning word contributes the whole instance, so an element reserves the cells its instance covers. Pure arithmetic over the `Op` data: no grid, no allocation. This is the measurement the emitter path uses; a `ValueNone` result means "greedy, stretch".

surface : Surface<'T>
body : Op<'T>[]
Returns: CellSize voption

mergeStyle (baseStyle, patch)

Full Usage: mergeStyle (baseStyle, patch)

Parameters:
Returns: Style

Field-wise cascade: the patch wins where it states a value.

baseStyle : Style
patch : Style
Returns: Style

noRepeatedProps (src, n)

Full Usage: noRepeatedProps (src, n)

Parameters:
    src : string
    n : Node

Returns: Result<unit, string>

Fails when a node states any property name more than once. The cascade kept the last value and the scalar readers kept the first, so a repeat says nothing about which one the author meant.

src : string
n : Node
Returns: Result<unit, string>

paintOf (surface, extent, body)

Full Usage: paintOf (surface, extent, body)

Parameters:
Returns: Element<'T>
Type parameters: 'T

The one closure per element: the body as data, interpreted at render time. The text produces nothing else that runs. The extent states a declared size; when none is declared, `measureOps` derives it from the body's own geometry (no allocation), so the emitter never needs the scratch-grid measure.

surface : Surface<'T>
extent : CellSize voption
body : Op<'T>[]
Returns: Element<'T>

reservedNames

Full Usage: reservedNames

Returns: FrozenSet<string>

Node kinds the vocabulary owns. A template or a surface element under one of these names would be unreachable, or would take over a container the resolver builds itself. `plot` and `grid` are not here: a template or a surface element of that name gives the built-in container its own body. Frozen: public but unmodifiable.

Returns: FrozenSet<string>

resolve surface src roots

Full Usage: resolve surface src roots

Parameters:
Returns: Result<Item<'T>[], string>
Type parameters: 'T

Templates expand, words resolve, style merges. Errors carry line and column when the front-end tracks positions (`Markup.where` turns each node's offset into them; XML nodes carry no positions, so their errors name the element). Cascade: solver defaults, then document `style` rules in order, then inline properties. `map` is the root container (its `w=`/`h=` dimensions are validated here); `element` nodes define templates (name as first argument or `name` property); `repeat n` duplicates its children; the `cols`, `rows` and `areas` properties of a container declare its tracks and named areas, and a `style` rule cannot state one. Declared `cols`/`rows` imply `pack=flow`. `plot` is the built-in anonymous container: empty body, exact box. `layer` is the map's layer container: one name and nothing else, resolved under the literal name `layer` and reported under its own (`Item.Layer`). Every root is the map or a declaration: a stray root node would be dropped without a word, so it fails the build.

surface : Surface<'T>
src : string
roots : ImmutableArray<Node>
Returns: Result<Item<'T>[], string>

resolveContainer (surface, src, templates, styles, name, n)

Full Usage: resolveContainer (surface, src, templates, styles, name, n)

Parameters:
Returns: Result<Item<'T>, string>
Type parameters: 'T

Resolves one container node into an `Item`: expands repeats, cascades the style (rule sheet, then inline props), splits the children into paint statements (this element's body), track and area directives, and child containers. Declarations (`element`, `style`) are leaves here — their collectors ran first. A `layer` child is legal only under the map root; it resolves under the literal name `layer` and the item is stamped with the layer's own name.

surface : Surface<'T>
src : string
templates : Dictionary<string, ElementDecl<'T>>
styles : Dictionary<string, Style>
name : string
n : Node
Returns: Result<Item<'T>, string>

resolveOp (surface, src, n)

Full Usage: resolveOp (surface, src, n)

Parameters:
Returns: Result<Op<'T>, string>
Type parameters: 'T

A statement reads its arguments by name: a property is a named slot (`rect edge=stone`), a positional argument fills the next slot in order. Leftovers of either kind are errors.

surface : Surface<'T>
src : string
n : Node
Returns: Result<Op<'T>, string>

rsOf v

Full Usage: rsOf v

Parameters:
    v : (int * int) voption

Returns: int
Modifiers: inline

The row span of a `colspan`/`rowspan` pair, or 1 when absent.

v : (int * int) voption
Returns: int

styleOfProps (src, n, baseStyle)

Full Usage: styleOfProps (src, n, baseStyle)

Parameters:
Returns: Result<Style, string>

Merges a node's inline properties over a base style, in document order; the first bad property fails with its position. A name stated twice fails before any of them applies.

src : string
n : Node
baseStyle : Style
Returns: Result<Style, string>

tracksOf (src, n, name)

Full Usage: tracksOf (src, n, name)

Parameters:
    src : string
    n : Node
    name : string

Returns: Result<Track[] voption, string>

Resolves one track list — `cols="1 fixed 3 auto"` — into tracks. A bare number is a weight, `fixed n` is a fixed size, `auto` sizes to the children. `Track.Percent` has no token: it carries a fraction of the container, and no document needs one yet.

src : string
n : Node
name : string
Returns: Result<Track[] voption, string>

validateSurface surface

Full Usage: validateSurface surface

Parameters:
Returns: Result<unit, string>
Type parameters: 'T

Game-declared element bodies never pass through statement resolution, so their kernel references and their area words get checked here: a typo, or a spanning word that an area statement cannot place, must fail the build rather than vanish at render.

surface : Surface<'T>
Returns: Result<unit, string>

wOf v

Full Usage: wOf v

Parameters:
Returns: int
Modifiers: inline

The `W` of a size, or 0 when absent — a half-stated `w=`/`h=` pair merges field-wise, so the missing axis reads 0 ("stretch this axis").

v : CellSize voption
Returns: int

wantInt (src, n, name, i)

Full Usage: wantInt (src, n, name, i)

Parameters:
    src : string
    n : Node
    name : string
    i : int

Returns: Result<int, string>

Reads one whole-number scalar by name first (the XML channel), then by positional index (the KDL channel).

src : string
n : Node
name : string
i : int
Returns: Result<int, string>

wantWord (src, n, name, i)

Full Usage: wantWord (src, n, name, i)

Parameters:
    src : string
    n : Node
    name : string
    i : int

Returns: Result<string, string>

Reads one word scalar by name first, then by positional index.

src : string
n : Node
name : string
i : int
Returns: Result<string, string>

xOf v

Full Usage: xOf v

Parameters:
Returns: int
Modifiers: inline

The `X` of a point, or 0 when absent — a half-stated `x=`/`y=` pair merges field-wise, so the missing axis reads 0.

v : CellPoint voption
Returns: int

yOf v

Full Usage: yOf v

Parameters:
Returns: int
Modifiers: inline

The `Y` of a point, or 0 when absent.

v : CellPoint voption
Returns: int

Type something to start searching.