# `Macaw.Layers.Fragment`
[🔗](https://github.com/dcoai/macaw_layers/blob/v0.3.0/lib/macaw/layers/fragment.ex#L1)

Fragments and stacking (spec/02): the fragment-type behavior, and the operations over
fragments of a type.

A **fragment** is a document of a type, or any part of one: a map with the type's keys,
not necessarily all of them and not validated. A document type that stacks implements
this behavior, declaring what visualize read from its chart schema: how each key
combines (`c:key/2`), which elements a layer replaces in place (`c:identity/2`), the kinds
its fragments can be (`c:kinds/0`, `c:wrapper/1`) and where each kind lands in a whole
document (`c:place/3`). The machinery holds no type's vocabulary, so every type combines
the same way:

- `compose/3`, the union, reports a name two fragments declare differently (§3.1);
- `stack/2`, the cascade, takes the higher layer's word (§3.2);
- `explain/2` says which layer set every value of a stack (§6.3);
- `kind/2`, `refs/2` and `relocate/3` read a fragment's kind and ids (§6.1, §6.2);
- `encode_value/2` and `decode_value/3` write and read variables, ids and use sites in
  the type's forms, and `name_map?/2` says where its name maps are (§9).

**A struct is a leaf of every walk** (visualize D-92): a `%Macaw.Layers.Var{}` stands for
a value rather than being one. Only `refs/2` and `relocate/3` read a struct's parts, a
`%Macaw.Layers.Use{}`'s, by name.

Ported from visualize's `Visualize.Chart.Compose`, `Stack` and `Fragment`.

# `id`

```elixir
@type id() :: {kind(), pos_integer()}
```

An id a store issued: `{kind, n}`.

# `kind`

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

A node kind of a document type.

# `layer`

```elixir
@type layer() :: map() | {term(), map()}
```

A layer of a stack: a fragment, or a `{name, fragment}` pair.

# `rule`

```elixir
@type rule() :: :concat | :union | :deep | :override | {:type, atom()}
```

How a key combines (spec/02 §2).

# `spec`

```elixir
@type spec() :: %{merge: rule(), node: kind() | nil, element: kind() | nil}
```

A key's spec: its rule, the node kind of a node-valued key, and the node kind of a
list's or a name map's elements.

# `bind_holes`
*optional* 

```elixir
@callback bind_holes(kind(), term(), term(), map()) :: term()
```

That value with its holes substituted, written back in the type's syntax.

# `decompose`
*optional* 

```elixir
@callback decompose(map()) :: [Macaw.Layers.Use.t()]
```

A whole document as inline sites, one kind each.

# `holes`
*optional* 

```elixir
@callback holes(kind(), term(), term()) :: [Macaw.Layers.Var.t()]
```

The variables a value of the type's own syntax holds (a text's holes).

# `identity`
*optional* 

```elixir
@callback identity(kind(), map()) :: term()
```

The identity of an element of a `:concat` list of `kind` elements, or `nil`.

# `inline`
*optional* 

```elixir
@callback inline(map(), (id() -&gt; {:ok, map()} | :error)) :: {map(), [{id(), list()}]}
```

Every id left at a reference site of a flattened document resolved through `fetch`.

# `key`

```elixir
@callback key(kind(), term()) :: spec() | nil
```

How a key of a node of `kind` combines, or `nil` for a key the type does not know.

# `kinds`

```elixir
@callback kinds() :: [kind()]
```

Every kind a fragment of the type can be, and so every kind an id can carry.

# `merge`
*optional* 

```elixir
@callback merge(atom(), term(), term()) :: term()
```

The type's own merge of a key whose rule is `{:type, name}`.

# `normalize`
*optional* 

```elixir
@callback normalize(kind(), term(), lower :: term(), higher :: term()) :: {term(), term()}
```

The two values a key of `kind` holds in both fragments, as they merge (spec/02 §3.3): a
type expands a shorthand on one side to the part the other side gives, so the two merge
key by key. Called only for a key both fragments hold.

# `place`

```elixir
@callback place(kind(), map(), String.t() | nil) :: {:ok, map()} | :keyless
```

Where a composite site of `kind` lands in a whole document (spec/02 §8.2).

# `place_whole`
*optional* 

```elixir
@callback place_whole(contribution :: map(), key :: String.t()) :: {:ok, map()}
```

A keyed site's contribution of no kind (a whole document, a multi-key fragment) as the
layer that declares it under the site's key (spec/02 §8.2). Without it, such a
contribution is its own layer.

# `root`

```elixir
@callback root() :: kind()
```

The node kind of a whole document of the type.

# `scope`
*optional* 

```elixir
@callback scope(composite :: map(), contribution :: map(), key :: String.t() | nil) ::
  map()
```

One resolved site's contribution as the composite holding it shapes it, before it is
placed (spec/02 §8.1): the composite node carries keys of the type's own besides `uses`
and `vars` (visualize's `defaults`), and this is where they reach the sites.

# `under`
*optional* 

```elixir
@callback under(kind(), lower :: map(), higher :: map()) :: map()
```

What of a lower node of `kind` the higher one, merging over it, keeps (spec/02 §3.3): a
node whose type changes keeps of the lower only what the new type still takes. A trim
is a replacement, so a stack where one happens is its left fold (§3.2).

# `wrapper`

```elixir
@callback wrapper(term()) :: kind() | nil
```

The kind a singular wrapper key names (`style:` → `:style`), or `nil`.

# `compose`

```elixir
@spec compose(module(), [map()]) ::
  {:ok, map()} | {:error, [Macaw.Layers.Fault.t(), ...]}
```

The left fold of `compose/3`; `compose(type, [])` is `{:ok, %{}}`.

# `compose`

```elixir
@spec compose(module(), map(), map()) ::
  {:ok, map()} | {:error, [Macaw.Layers.Fault.t(), ...]}
```

`b` over `a` by every key's rule (spec/02 §3.1): `{:ok, fragment}`, or `{:error, faults}`
with every `:conflict` at its path, ordered by path.

# `decode_value`

```elixir
@spec decode_value(module(), String.t(), term()) :: {:ok, term()} | :default
```

The value of one of this file's tags, its payload already read (spec/02 §9), for a
type's `decode_value/2` to call: `{:ok, value}`, or `:default` for a tag or payload it
does not read, which the reader refuses at its path. An id's kind is matched against the
type's kinds by its string, so no atom is made from a document.

# `encode_value`

```elixir
@spec encode_value(module(), term()) :: {:ok, term()} | :default
```

The map form of this file's terms (spec/02 §9), for a type's `encode_value/1` to call:
a variable as `{"$var": name}`, an id as `{"$id": [kind, n]}`, a use site as
`{"$use": {…}}`, its parts in the type's own map form; `:default` for any other term.

# `explain`

```elixir
@spec explain(module(), [layer()]) :: [map()]
```

One entry per leaf path of `stack/2` of `layers` (spec/02 §6.3), ordered by path:
`%{path, value, layer, overrode}`, `layer` the layer's name or its zero-based position.
It recomputes the stack by the cascade's own walk, so it cannot drift from it.

# `kind`

```elixir
@spec kind(module(), map()) :: kind() | nil
```

The kind of a fragment, derived (spec/02 §6.1): walking down while exactly one key is
set, the last kind reached. A singular wrapper is the kind it names, a name map or list
holding one entry the entry's kind, a composite `:composite`. `nil` for a fragment that
branches at the top, which is no kind of fragment, and for one that reaches no kind
below the root.

# `name_map?`

```elixir
@spec name_map?(module(), [term()]) :: boolean()
```

Whether the map at `path` in a document of the type is a name map (spec/02 §9), derived
from the type's specs, for a type's `Macaw.Layers.Form.name_map?/1` to call. Walking the
path from the root node: a `:union` or `:deep` key holds a name map, whose every entry is
a node of the key's `element` kind; a key with a `node` kind leads to a node of it, and
so does a singular wrapper key at the root; a `:concat` key holds a list whose every
element is a node of its `element` kind. Anything else is a leaf, never a name map.

Below a tag (`{:tag, tag}` first, spec/01 §6), a use site's `local` is a fragment of the
type, so its maps are at the type's positions from the root; every other payload's maps
are nodes.

    iex> Macaw.Layers.Fragment.name_map?(Macaw.Layers.Theme.Document, [:theme, :styles])
    true
    iex> Macaw.Layers.Fragment.name_map?(Macaw.Layers.Theme.Document, [:theme, :styles, "x"])
    false

# `refs`

```elixir
@spec refs(module(), term()) :: [id()]
```

Every id a fragment refers to, once each, sorted (spec/02 §6.2): a `{kind, n}` of the
type's `c:kinds/0` with `n` a positive integer, wherever it stands, a use site's `ref`,
`origin`, `local` and `vars` included. Sorted, since the order a map is walked is the
runtime's.

# `relocate`

```elixir
@spec relocate(module(), term(), %{required(id()) =&gt; id()}) :: {term(), [id()]}
```

The fragment with every id rewritten through `table`, `%{old => new}`, and the ids the
table did not carry, sorted (spec/02 §6.2). A use site's ids are rewritten in place, the
site still a `%Use{}`; an id not in the table is left, to resolve as a mask.

# `stack`

```elixir
@spec stack(module(), [layer()]) :: map()
```

The left fold of `stack/3`, the later layer the higher: `stack(type, [])` is `%{}` and
`stack(type, [a])` is `a`. A layer may be a `{name, fragment}` pair, whose name is
ignored here and reported by `explain/2`.

# `stack`

```elixir
@spec stack(module(), map(), map()) :: map()
```

The cascade of `higher` over `lower` (spec/02 §3.2): for every key the higher layer
wins. It cannot fail, so it answers the fragment itself.

---

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