packages feed

phino 0.0.150 → 0.0.151

raw patch · 20 files changed

+1497/−938 lines, 20 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Deps: EvFormation :: Int -> Expression -> Expression -> Evaluation
+ Deps: EvDelta :: Int -> Bytes -> Evaluation
+ Deps: EvStarted :: Int -> Judgment -> Expression -> Evaluation
+ Deps: [_answered] :: Protocol -> [(Int, Expression, String)]
+ Deps: [_blocks] :: Protocol -> [(Int, Maybe String, Bool)]
+ Deps: [_datums] :: Nesting -> Map Int Int
+ Deps: [_deltas] :: Protocol -> Map Int Int
+ Deps: [_found] :: Protocol -> Maybe (Bytes, String)
+ Deps: [_heads] :: Nesting -> [(Int, String)]
+ Deps: [_held] :: Nesting -> Maybe (Bytes, String)
+ Deps: [_pending] :: Nesting -> [(Int, String, String)]
+ Deps: [_sources] :: Nesting -> [(Int, Expression, String)]
+ Deps: found :: Either Int Bytes -> Maybe (Bytes, String) -> Maybe String
+ Deps: ieee :: Bytes -> Maybe String
+ Deps: resited :: Expression -> Expression -> Evaluation -> Evaluation
+ Deps: sigil :: Text
+ Morph: [_opened] :: ReduceContext -> Maybe (Int, Judgment, Expression)
+ Morph: opening :: Judgment -> ReduceContext -> IO ReduceContext
+ Yaml: validateKnownYamlKeys :: MonadFail a => Object -> [String] -> a ()
- Deps: Nesting :: Int -> [(Int, Int)] -> [(Int, String)] -> Named Expression -> Map Int Int -> Nesting
+ Deps: Nesting :: Int -> [(Int, Int)] -> [(Int, String)] -> Named Expression -> Map Int Int -> Map Int Int -> Maybe (Bytes, String) -> [(Int, String)] -> [(Int, String, String)] -> [(Int, Expression, String)] -> Nesting
- Deps: Protocol :: Int -> Named Text -> [(Int, Int)] -> Bool -> Named Expression -> Map Int Int -> Map Int Int -> Protocol
+ Deps: Protocol :: Int -> Named Text -> [(Int, Int)] -> Bool -> Named Expression -> Map Int Int -> Map Int Int -> Map Int Int -> Maybe (Bytes, String) -> [(Int, Maybe String, Bool)] -> [(Int, Expression, String)] -> Protocol
- Morph: ReduceContext :: Expression -> Expression -> Maybe Expression -> Int -> Int -> Steps -> Maybe Tally -> IORef Int -> Maybe Deadline -> Maybe Memo -> Int -> Bool -> Bool -> Bool -> Bool -> Int -> Maybe Acyclic -> Judgment -> [Text] -> Seen -> Lambdas -> BuildTermFunc -> ReductionFunc -> EvaluationFunc -> FiringFunc -> SaveStepFunc -> SaveEvalFunc -> Engine -> ReduceContext
+ Morph: ReduceContext :: Expression -> Expression -> Maybe Expression -> Int -> Int -> Steps -> Maybe Tally -> IORef Int -> Maybe Deadline -> Maybe Memo -> Int -> Maybe (Int, Judgment, Expression) -> Bool -> Bool -> Bool -> Bool -> Int -> Maybe Acyclic -> Judgment -> [Text] -> Seen -> Lambdas -> BuildTermFunc -> ReductionFunc -> EvaluationFunc -> FiringFunc -> SaveStepFunc -> SaveEvalFunc -> Engine -> ReduceContext

Files

README.md view
@@ -55,6 +55,23 @@ * MacOS (Intel): <http://phino.objectionary.com/releases/macos-14-large/phino-latest> * Windows: <http://phino.objectionary.com/releases/windows-2022/phino-latest.exe> +In a [GitHub Actions][gha] workflow, one step downloads the binary+for the runner and puts it on the `PATH`:++```yaml+- uses: objectionary/phino@0.0.150+  with:+    version-file: phino-version.txt+- run: phino --version+```++The file holds the version to install, such as `0.0.150`, and the+whitespace around it is ignored.+Give `version: 0.0.150` instead of `version-file` to write the version+in the workflow itself.+The step fails if no binary is released for the runner, such as+Linux on ARM, or if `phino --version` prints another version.+ ## Build  To build `phino` from source, clone this repository:@@ -373,9 +390,8 @@ Every λ function fired on the way to the answer may be recorded in a machine-readable protocol, with the `--protocol` option. The protocol is a tree: the run at the top, one block per firing under it, and inside the block-the operands the firing bound and the term it answered with. A formation that-dataization gets into opens a block too, and what fires inside it stands under-it.+the operands the firing bound and the term it answered with. A judgment started+at a new site opens a block too, and what it does stands under it.  <!-- markdownlint-disable MD013 --> @@ -383,93 +399,108 @@ $ phino dataize --symbolic=atoms.yaml --protocol=atoms.txt --quiet \     --sweet --hide-rho sum.phi $ cat atoms.txt-𝔻(Φ)-  formation(⟦ bytes(φ) ↦ ⟦⟧, number(φ) ↦ ⟦ plus(x) ↦ L_number_plus:λ ⟧, φ ↦ 5.plus( 6 ) ⟧)  # 𝔻(Φ)-    applied(𝑛.0.1) := 5  # 𝕄(Φ)-    applied(𝑛.0.2) := 𝑛.0.1.plus( x ↦ 6 )  # 𝕄(Φ)-    𝔼(L_number_plus)  # 𝔻(Φ)-      applied(𝑛.1.1) := 5  # 𝕄(Φ.a🌵0)-      formation(𝑛.1.1)  # 𝔻(Φ.a🌵0)-        applied(𝑛.1.2) := Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵0)-        formation(𝑛.1.2)  # 𝔻(Φ.a🌵0)-      𝛿1.1 := 40-14-00-00-00-00-00-00  # 𝔻(ξ.ρ)-      applied(𝑛.1.3) := 6  # 𝕄(Φ.a🌵1)-      formation(𝑛.1.3)  # 𝔻(Φ.a🌵1)-        applied(𝑛.1.4) := Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵1)-        formation(𝑛.1.4)  # 𝔻(Φ.a🌵1)-      𝛿2.1 := 40-18-00-00-00-00-00-00  # 𝔻(ξ.x)-      𝑛.1.5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛-      applied(𝑛.1.6) := Φ.number( φ ↦ 𝜎1:λ )  # 𝕄(Φ)-      𝑛.1.7 := 𝑛.1.6  # 𝕄(𝑛.1.5)-    formation(𝑛.1.6)  # 𝔻(Φ)+𝔻(Φ):+  𝕄(Φ):+    𝑛·0·1 := 5+    𝑛·0·2 := 𝑛·0·1.plus( x ↦ 6 )+  𝔼(L_number_plus):+    𝔻(Φ.a🌵0):+      𝕄(Φ.a🌵0):+        𝑛·1·1 := 5+        𝑛·1·2 := Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )+      𝛿·1·1 := 40-14-00-00-00-00-00-00  # 5.0+    𝛿1·1 := 𝛿·1·1  # 𝔻(ξ.ρ)+    𝔻(Φ.a🌵1):+      𝕄(Φ.a🌵1):+        𝑛·1·3 := 6+        𝑛·1·4 := Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )+      𝛿·1·2 := 40-18-00-00-00-00-00-00  # 6.0+    𝛿2·1 := 𝛿·1·2  # 𝔻(ξ.x)+    𝑛·1·5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛+    𝕄(𝑛·1·5):+      𝑛·1·6 := Φ.number( φ ↦ 𝜎1:λ )+    𝑛·1·7 := 𝑛·1·6  # 𝕄(𝑛·1·5) ```  <!-- markdownlint-enable MD013 -->  `𝔻(…)` is the run and the term it was aimed at, `𝕄(…)` where the run is a-morphing, and `𝔼(…)` is one firing, named by the entry that answered it and-commented with the judgment that asked for it and the site it was fired at.-Every comment of the file is of that shape: a judgment applied to a term, which-is the intent the value beside it came from. The firings are numbered across the-whole run, in the order they open, so `𝛿1.2` is the value bound to `𝛿1` by-the second firing of the run, whichever λ function that was, `𝑛1.2` the same-for a `morph` meta, and `𝑛.3.2` the answer of the third firing, so-`𝑛1.2 := 𝑛.3.2` reads "the `𝑛1` of this firing is what the third firing+morphing, and `𝔼(…)` is one firing, named by the entry that answered it. A line+standing in a block needs no comment to say which judgment made it and where:+the block it stands in says that already. A comment is written only where it+says something the block does not, such as the term an operand was reduced+from, `𝔻(ξ.ρ)`, or the meta an answer was read from, `𝑛`, and every comment+naming a judgment is of that shape: a judgment applied to a term, which is the+intent the value beside it came from. The firings are numbered across the+whole run, in the order they open, so `𝛿1·2` is the value bound to `𝛿1` by+the second firing of the run, whichever λ function that was, `𝑛1·2` the same+for a `morph` meta, and `𝑛·3·2` the answer of the third firing, so+`𝑛1·2 := 𝑛·3·2` reads "the `𝑛1` of this firing is what the third firing answered". One firing binds a meta once and no two firings share a number, so every one of these names stands on exactly one line of the file and a line naming another one points at it and no other. -`formation(…)` is a formation 𝔻 got into through its `box` rule, which-dataizes the `φ` of a formation carrying neither `Δ` nor `λ`. It is commented-with `𝔻` and the site it was entered at, the way a firing is, and what the `φ`-body does stands one level deeper under it: the firings its dataization-demands, and the formations it gets into in turn. A reader therefore sees which-object a firing was made on the way into, rather than a flat list of firings.-Only `box` writes one, since 𝕄 stops at a formation without getting into it-and a formation whose λ is fired is already an `𝔼(…)` block. The line is no-firing: it binds no meta and takes no number, so the metas of the firings under-it are numbered as if it were not there. In the run above 𝔻 gets into the-program itself, since `Φ` binds `φ`; then into each number the entry brings-down, and through its `φ` into the bytes that number holds; and last into the-number the entry answered, whose `φ` is the symbol `𝜎1`, so nothing fires under-that one.+A nested `𝔻(…):` or `𝕄(…):` line opens a block where a judgment starts at a+site other than the one of the block it stands in, and names that site. What+the judgment does stands one level deeper under it: the objects its+normalization makes, the firings it demands, and the judgments it starts in+turn. A reader therefore sees which judgment made each line and at which site,+rather than a flat list of lines each saying so. 𝔻 of a term that is no+formation asks 𝕄 for the normal form of the same term first, through its+`norm` rule, so a `𝕄(…):` block often stands right inside a `𝔻(…):` block of+the same site, and `𝑛·0·1 := 5` above is made by that 𝕄 and not by 𝔻. A+judgment started at the site of the block it stands in, and by the same+judgment, opens nothing, and what it does joins that block. A block is written+only once a line stands in it, so a judgment that made nothing worth a line+leaves no empty heading behind. The line is no firing: it binds no meta and+takes no number, so the metas of the firings under it are numbered as if it+were not there. A `𝔻(…):` block ends with the datum the `delta` rule found,+such as `𝛿·1·1 := 40-14-00-00-00-00-00-00`, named by the firing it stands in+and a counter of its own, and the operand line right after the block names it.+A datum of eight bytes is commented with the number those bytes hold as an+IEEE 754 double, `# 5.0` here, since that is how a number keeps its data.+In the run above 𝔻 gets into each number the entry brings down, and through+its `φ` into the bytes that number holds, in the same block, since the site is+the same.  An answer stands on two lines and not one. A firing answers the term its entry wrote and `phino` morphs that term before standing it back into the program, so-`𝑛.1.5` is what the entry wrote, with the symbols this firing minted already in-it, commented with `𝑛` to name the key it was read from, and `𝑛.1.7` is the-normal form 𝕄 made of it, commented with `𝕄(𝑛.1.5)` to say where it came from.-It is the same morphing every other term goes through, and writing only its+`𝑛·1·5` is what the entry wrote, with the symbols this firing minted already in+it, commented with `𝑛` to name the key it was read from, and `𝑛·1·7` is the+normal form 𝕄 made of it, commented with `𝕄(𝑛·1·5)` to say where it came from.+That morphing opens a block of its own, `𝕄(𝑛·1·5):`, named after the term it+started from, since that term stands nowhere in the program a locator could+reach. It is the same morphing every other term goes through, and writing only its outcome would have the formation of `number` appear in place of the three tokens the entry wrote with nothing saying why. Whatever that morphing fires or applies writes its lines between the two, exactly where a firing an operand took opens its block, so the order the lines come in is the order the work was done in. -`applied(𝑛.1.6) := Φ.number( φ ↦ 𝜎1:λ )  # 𝕄(Φ)` is an object an application-made. The `copy` rule of normalization fills a void of a formation with the-argument it was given, and so makes a new object, whatever judgment is running-and wherever in the term the application stands. The line binds that object to-a fresh `𝑛` and spells the application: the object applied on the left and the-argument it got on the right, so `5` is `Φ.number( φ ↦ … )` in sugar. The `ρ` a-dispatch gives the attribute it takes writes no line. The comment names the+`𝑛·1·6 := Φ.number( φ ↦ 𝜎1:λ )` is an object an application made. The `copy`+rule of normalization fills a void of a formation with the argument it was+given, and so makes a new object, whatever judgment is running and wherever in+the term the application stands. The line binds that object to a fresh `𝑛` and+spells the application: the object applied on the left and the argument it got+on the right, so `5` is `Φ.number( φ ↦ … )` in sugar. The `ρ` a dispatch gives+the attribute it takes writes no line. The block the line stands in names the judgment that normalized and the site it stood at. The name is counted with the-metas of the firing the line stands in, `𝑛.1.5` before it and `𝑛.1.7` after it,-and an object made outside every firing is counted under `𝑛.0`. From then on+metas of the firing the line stands in, `𝑛·1·5` before it and `𝑛·1·7` after it,+and an object made outside every firing is counted under `𝑛·0`. From then on every line spells the object by that name rather than as the formation it is, and the application by the same name, since `copy` makes the same object of the-same application wherever it stands: `formation(𝑛.1.1)` is the object `5` made,-`𝑛.0.1.plus( x ↦ 6 )` is the `plus` of the first `5` applied to `6`, one line-for one call, and `𝑛.1.7 := 𝑛.1.6` says the firing answered with the object 𝕄-made of what the entry wrote. An `applied` line names its head and its argument-that way, each on its own, and never the application as a whole, so a line-spells out every application, even one making an object an earlier one already-made, the way `applied(𝑛.1.1) := 5` does, and a later line names the latest of-them. Only an object still standing as it was made is named: once a rule-rewrote a part of it, it is another object and it is spelled out again. The-walk of `--deep` is no such rule. It stands its answers in the place of what it-computed, inside the bindings of the object it walks, and makes no new object-by doing so, so the object keeps its name once the walk is done with it.+same application wherever it stands: `𝑛·1·1` is the object `5` made,+`𝑛·0·1.plus( x ↦ 6 )` is the `plus` of the first `5` applied to `6`, one line+for one call, and `𝑛·1·7 := 𝑛·1·6` says the firing answered with the object 𝕄+made of what the entry wrote. Such a line names its head and its argument that+way, each on its own, and never the application as a whole, so a line spells out+every application, even one making an object an earlier one already made, the+way `𝑛·1·1 := 5` does, and a later line names the latest of them. Only an object+still standing as it was made is named: once a rule rewrote a part of it, it is+another object and it is spelled out again. The walk of `--deep` is no such+rule. It stands its answers in the place of what it computed, inside the+bindings of the object it walks, and makes no new object by doing so, so the+object keeps its name once the walk is done with it.  Where an operand came down to the datum a symbol stands for, the protocol writes `𝔻(𝜎1:λ)` in place of that 42 (`𝜎1:λ` is the formation `⟦ λ ⤍ 𝜎1 ⟧`, in the@@ -486,20 +517,25 @@ symbol with such a fact as a constant and every other symbol as an unknown.  The line binding the term of a `symbolize` one is commented with the meta it-was told to stand, `𝑛3.1 := ⟦ λ ⤔ 𝜆8 ⟧  # 𝑛1`, and with no judgment+was told to stand, `𝑛3·1 := ⟦ λ ⤔ 𝜆8 ⟧  # 𝑛1`, and with no judgment around it: standing the data of a term into unknowns is the file's own operation and nothing of the calculus runs there, so the line names a meta of the entry the way a `join` line names the two it joined. A comment carries the-letter of a judgment exactly where a judgment made the value.+letter of a judgment exactly where a judgment made the value and the block+around the line does not already say so. -The site of a firing is a locator, written as a comment the way an operand-line writes the term it came from, under the letter of the judgment that asked-for the firing: 𝔼 is fired by the `ml` rule of morphing and by the `fire` rule-of dataization, so `𝕄(Φ.demo.a.φ)` is a λ function fired while 𝕄 was reducing-that binding and `𝔻(Φ)` one fired because dataization demanded data of `Φ`.-A chain such as `5.plus( 6 ).plus( 7 )` writes both: the inner call is fired-while 𝕄 reduces the head of the outer dispatch, the outer one because 𝔻 asked-for the data. The site itself is where in the program the firing+The site of a firing is a locator, and the block a firing stands in names it,+under the letter of the judgment that asked for the firing: 𝔼 is fired by the+`ml` rule of morphing and by the `fire` rule of dataization, so a firing in the+block `𝕄(Φ.demo.a.φ):` is a λ function fired while 𝕄 was reducing that+binding, and one standing right in `𝔻(Φ):` was fired because dataization+demanded data of `Φ`. A chain such as `5.plus( 6 ).plus( 7 )` writes both: the+inner call is fired inside the `𝕄(Φ):` block, while 𝕄 reduces the head of the+outer dispatch, and the outer one right in `𝔻(Φ):`, because 𝔻 asked for the+data. A line standing right in a firing has no block of its own around it, so+a line there that a judgment wrote at a site no block names, such as+`starved(…)` below, carries that judgment and site as its comment. The site+itself is where in the program the firing belongs: the term the run was aimed at, so `Φ` for a run that was aimed at nothing in particular, and, under `--deep`, the binding the walk had entered when the λ function fired, since that walk reduces every part of the program@@ -515,9 +551,9 @@ An operand line ends in the judgment that reduced it and the term it was reduced from, written as a comment after two spaces and `#`. The value alone says what the meta was bound to and neither what it was bound from nor what-was done to it, so `𝛿1.1 := 40-14-00-00-00-00-00-00  # 𝔻(ξ.ρ)` reads "the-`𝛿1` of this firing is the `ρ` of the formation brought down through 𝔻, and-it came down to 20", where a `morph` operand reads `𝑛1.5 := 𝑛.3.2  # 𝕄(ξ.then)`+was done to it, so `𝛿1·1 := 𝛿·1·1  # 𝔻(ξ.ρ)` reads "the `𝛿1` of this firing+is the `ρ` of the formation brought down through 𝔻, and it came down to the+datum `𝛿·1·1` above", where a `morph` operand reads `𝑛1·5 := 𝑛·3·4  # 𝕄(ξ.then)` and says that the `then` of the formation reached its normal form through 𝕄. Which of the two judgments ran is the whole difference between a line ending in data and one ending in a term. It is the very term the entry wrote under@@ -528,13 +564,13 @@ `unanswered(…)` is a λ name no entry answers, standing where the block of its firing would have stood. Nothing fired, so nothing opens under it. The line is commented with the judgment that asked and the formation it was asking about,-`𝕄(L_none:λ)`, the way an operand line is commented with the term it was-reduced from: 𝔼 is fired by the `ml` rule of morphing and by the `fire` rule-of dataization, so the letter says where in the reduction the site stands and-the term says which object the λ function that could not fire belongs to. It-is written-whether or not `--partial` goes on to park the run, since the protocol records-what 𝔼 was asked for, and a question it could not answer belongs there as much+`𝕄(L_none:λ)`, which no block names, the way an operand line is commented+with the term it was reduced from: 𝔼 is fired by the `ml` rule of morphing+and by the `fire` rule of dataization, so the letter says where in the+reduction the site stands and the term says which object the λ function that+could not fire belongs to. It is written whether or not `--partial` goes on+to park the run, since the protocol records what 𝔼 was asked for, and a+question it could not answer belongs there as much as one it could — once per site and not once per attempt, since a site `--partial` parks stays in the residue and `--deep` walks over it again: @@ -545,25 +581,28 @@     --sweet --hide-rho stuck.phi [ERROR]: No entry of --symbolic answers the λ function 'L_number_nope' $ cat atoms.txt-𝔻(Φ)-  formation(⟦ bytes(φ) ↦ ⟦⟧, number(φ) ↦ ⟦ plus(x) ↦ L_number_plus:λ, nope ↦ L_number_nope:λ ⟧, φ ↦ 5.plus( 6 ).nope ⟧)  # 𝔻(Φ)-    applied(𝑛.0.1) := 5  # 𝕄(Φ)-    applied(𝑛.0.2) := 𝑛.0.1.plus( x ↦ 6 )  # 𝕄(Φ)-    𝔼(L_number_plus)  # 𝕄(Φ)-      applied(𝑛.1.1) := 5  # 𝕄(Φ.a🌵0)-      formation(𝑛.1.1)  # 𝔻(Φ.a🌵0)-        applied(𝑛.1.2) := Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵0)-        formation(𝑛.1.2)  # 𝔻(Φ.a🌵0)-      𝛿1.1 := 40-14-00-00-00-00-00-00  # 𝔻(ξ.ρ)-      applied(𝑛.1.3) := 6  # 𝕄(Φ.a🌵1)-      formation(𝑛.1.3)  # 𝔻(Φ.a🌵1)-        applied(𝑛.1.4) := Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵1)-        formation(𝑛.1.4)  # 𝔻(Φ.a🌵1)-      𝛿2.1 := 40-18-00-00-00-00-00-00  # 𝔻(ξ.x)-      𝑛.1.5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛-      applied(𝑛.1.6) := Φ.number( φ ↦ 𝜎1:λ )  # 𝕄(Φ)-      𝑛.1.7 := 𝑛.1.6  # 𝕄(𝑛.1.5)-    unanswered(L_number_nope)  # 𝔻(L_number_nope:λ)+𝔻(Φ):+  𝕄(Φ):+    𝑛·0·1 := 5+    𝑛·0·2 := 𝑛·0·1.plus( x ↦ 6 )+    𝔼(L_number_plus):+      𝔻(Φ.a🌵0):+        𝕄(Φ.a🌵0):+          𝑛·1·1 := 5+          𝑛·1·2 := Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )+        𝛿·1·1 := 40-14-00-00-00-00-00-00  # 5.0+      𝛿1·1 := 𝛿·1·1  # 𝔻(ξ.ρ)+      𝔻(Φ.a🌵1):+        𝕄(Φ.a🌵1):+          𝑛·1·3 := 6+          𝑛·1·4 := Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )+        𝛿·1·2 := 40-18-00-00-00-00-00-00  # 6.0+      𝛿2·1 := 𝛿·1·2  # 𝔻(ξ.x)+      𝑛·1·5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛+      𝕄(𝑛·1·5):+        𝑛·1·6 := Φ.number( φ ↦ 𝜎1:λ )+      𝑛·1·7 := 𝑛·1·6  # 𝕄(𝑛·1·5)+  unanswered(L_number_nope)  # 𝔻(L_number_nope:λ) ```  <!-- markdownlint-enable MD013 -->@@ -580,36 +619,43 @@ `stall(L_outer)` stands under a firing that `--acyclic=plausible` answered with the stall an earlier firing of the same formation kept, so a told stall never reads as a fresh firing that wrote nothing.-`starved(4)  # 𝔻(Φ.a🌵1)` is where `--max-steps=4` ran out, commented with the-judgment and the site the reduction stood at, whether or not `--partial` goes-on to park it:+`starved(3)` is where `--max-steps=3` ran out, whether or not `--partial` goes+on to park it. It stands in the block of the judgment and the site the+reduction stood at, and where the budget ran out before that block could open,+right in a firing, it is commented with them instead, `starved(3)  # 𝔻(Φ.a🌵2)`:  ```text-𝕄(Φ.x)-  𝔼(L_outer)  # 𝕄(Φ.x)-    𝔼(L_outer)  # 𝔻(Φ.a🌵0)-      starved(4)  # 𝔻(Φ.a🌵1)+𝕄(Φ.x):+  𝕄(Φ.x.arg):+    𝔼(L_outer):+      𝔻(Φ.a🌵0):+        starved(3)+      stuck(L_outer)+  𝔼(L_outer):+    𝔻(Φ.a🌵1):+      𝔼(L_outer):+        starved(3)  # 𝔻(Φ.a🌵2)     stuck(L_outer) ```  The markup spells them `<unfinished λ="L_outer"/>`, `<stall λ="L_outer"/>`-and `<starved limit="4" by="dataize" at="Φ.a🌵1"/>`.+and `<starved limit="3" by="dataize" at="Φ.a🌵2"/>`. -`timeout(5)  # 𝕄(…)` is where `--max-seconds=5` ran out, commented the same+`timeout(5)` is where `--max-seconds=5` ran out, placed and commented the same way and written at the first step the deadline refused. The run ends there, with or without `--partial`, so it is always the last line of the protocol. The markup spells it `<timeout limit="5" by="morph" at="…"/>`. -`spent(3)  # 𝔻(…)` is where `--max-firings=3` ran out, commented the same way-and written where the firing it refused would have started.+`spent(3)` is where `--max-firings=3` ran out, placed and commented the same+way and written where the firing it refused would have started. The markup spells it `<spent limit="3" by="dataize" at="…"/>`. -`deferred(𝜎2) := Φ.box( x ↦ 𝜎1:λ )  # 𝕄(Φ.y)` is a copy the deep walk+`deferred(𝜎2) := Φ.box( x ↦ 𝜎1:λ )` is a copy the deep walk deferred instead of entering it. The fresh symbol it answered the copy with stands in parentheses. The copy is written as a call of the object of the world-it was made of, given the arguments that fill its voids, read. The comment-names the judgment and the site of the walk.+it was made of, given the arguments that fill its voids, read. The block it+stands in names the judgment and the site of the walk. The object is found through the `ρ` of the copy: no `ρ` means `Φ`, a `ρ` that is a name means that name with its applications erased, and a `ρ` that is a formation means the object that formation was made of. Among the formations@@ -617,21 +663,21 @@ whose voids it fills the most, and which shares the most bindings with it. When the world declares no such object, or two of them tie, the copy is written as it stood, such as `⟦ x ↦ 𝜎1:λ, φ ↦ x.next ⟧`, or by the name the-`applied` line of the application that made it gave it, such as `𝑛.0.1`.+line of the application that made it gave it, such as `𝑛·0·1`. The markup spells it on one line, broken here for reading. The object stands in `of` and the arguments in `<with>`, both written whatever `--abridged` says, and the copy as it stood stands in `<e>`, abridged and named as usual:  ```xml-<applied meta="𝑛.0.1" by="morph" at="Φ.y" of="Φ.box"><attr name="x">𝜎1</attr></applied>+<applied meta="𝑛·0·1" by="morph" at="Φ.y" of="Φ.box"><attr name="x">𝜎1</attr></applied> <deferred symbol="𝜎2" by="morph" at="Φ.y" of="Φ.box">   <with><attr name="x">𝜎1</attr></with>-  <e>𝑛.0.1</e>+  <e>𝑛·0·1</e> </deferred> ```  A deferred copy is one the walk did not make: the application that made it-writes its own `applied` line, and the `deferred` line says what the walk did+writes its own line, and the `deferred` line says what the walk did not do with that object.  Every argument of the call is an `<attr>` of `<with>`. An argument that is a@@ -688,53 +734,114 @@ $ phino morph --deep --symbolic=atoms.yaml --locator=Q.demo.a \     --protocol=fork.txt --quiet --sweet --hide-rho fork.phi $ cat fork.txt-𝕄(Φ.demo.a)-  𝔼(L_gt)  # 𝕄(Φ.demo.a.φ)-    formation(⟦ φ ↦ 𝜎1:λ, plus(x) ↦ L_plus:λ, gt(x) ↦ L_gt:λ ⟧)  # 𝔻(Φ.a🌵0)-    𝛿1.1 := 𝔻(𝜎1:λ)  # 𝔻(ξ.ρ)-    formation(⟦ φ ↦ Φ.bytes( φ ↦ 00-00-00-00-00-00-00-00:Δ ), plus(x) ↦ L_plus:λ, gt(x) ↦ L_gt:λ ⟧)  # 𝔻(Φ.a🌵1)-      formation(00-00-00-00-00-00-00-00:Δ:φ)  # 𝔻(Φ.a🌵1)-    𝛿2.1 := 00-00-00-00-00-00-00-00  # 𝔻(ξ.x)-    𝑛.1.1 := Φ.bool( if(then, else) ↦ ⟦ λ ⤍ L_fork, φ ↦ 𝜎2:λ ⟧ )  # 𝑛-    𝑛.1.2 := ⟦ if(then, else) ↦ ⟦ λ ⤍ L_fork, φ ↦ 𝜎2:λ ⟧ ⟧  # 𝕄(𝑛.1.1)-  𝔼(L_plus)  # 𝕄(Φ.demo.a.φ)-    formation(⟦ φ ↦ 𝜎1:λ, plus(x) ↦ L_plus:λ, gt(x) ↦ L_gt:λ ⟧)  # 𝔻(Φ.a🌵2)-    𝛿1.2 := 𝔻(𝜎1:λ)  # 𝔻(ξ.ρ)-    formation(⟦ φ ↦ Φ.bytes( φ ↦ 3F-F0-00-00-00-00-00-00:Δ ), plus(x) ↦ L_plus:λ, gt(x) ↦ L_gt:λ ⟧)  # 𝔻(Φ.a🌵3)-      formation(3F-F0-00-00-00-00-00-00:Δ:φ)  # 𝔻(Φ.a🌵3)-    𝛿2.2 := 3F-F0-00-00-00-00-00-00  # 𝔻(ξ.x)-    𝑛.2.1 := Φ.number( φ ↦ 𝜎3:λ )  # 𝑛-    𝑛.2.2 := ⟦ φ ↦ 𝜎3:λ, plus(x) ↦ L_plus:λ, gt(x) ↦ L_gt:λ ⟧  # 𝕄(𝑛.2.1)-  𝔼(L_plus)  # 𝕄(Φ.demo.a.φ)-    formation(⟦ φ ↦ 𝜎1:λ, plus(x) ↦ L_plus:λ, gt(x) ↦ L_gt:λ ⟧)  # 𝔻(Φ.a🌵4)-    𝛿1.3 := 𝔻(𝜎1:λ)  # 𝔻(ξ.ρ)-    formation(⟦ φ ↦ 𝜎3:λ, plus(x) ↦ L_plus:λ, gt(x) ↦ L_gt:λ ⟧)  # 𝔻(Φ.a🌵5)-    𝛿2.3 := 𝔻(𝜎3:λ)  # 𝔻(ξ.x)-    𝑛.3.1 := Φ.number( φ ↦ 𝜎4:λ )  # 𝑛-    𝑛.3.2 := ⟦ φ ↦ 𝜎4:λ, plus(x) ↦ L_plus:λ, gt(x) ↦ L_gt:λ ⟧  # 𝕄(𝑛.3.1)-  𝔼(L_plus)  # 𝕄(Φ.demo.a.φ)-    formation(⟦ φ ↦ 𝜎1:λ, plus(x) ↦ L_plus:λ, gt(x) ↦ L_gt:λ ⟧)  # 𝔻(Φ.a🌵6)-    𝛿1.4 := 𝔻(𝜎1:λ)  # 𝔻(ξ.ρ)-    formation(⟦ φ ↦ 𝜎1:λ, plus(x) ↦ L_plus:λ, gt(x) ↦ L_gt:λ ⟧)  # 𝔻(Φ.a🌵7)-    𝛿2.4 := 𝔻(𝜎1:λ)  # 𝔻(ξ.x)-    𝑛.4.1 := Φ.number( φ ↦ 𝜎5:λ )  # 𝑛-    𝑛.4.2 := ⟦ φ ↦ 𝜎5:λ, plus(x) ↦ L_plus:λ, gt(x) ↦ L_gt:λ ⟧  # 𝕄(𝑛.4.1)-  𝔼(L_fork)  # 𝕄(Φ.demo.a.φ)-    𝛿1.5 := 𝔻(𝜎2:λ)  # 𝔻(ξ.φ)-    𝑛1.5 := 𝑛.3.2  # 𝕄(ξ.then)-    𝑛2.5 := 𝑛.4.2  # 𝕄(ξ.else)-    𝔻(𝜎6:λ) ∈ { 𝔻(𝜎4:λ), 𝔻(𝜎5:λ) }-    𝑛3.5 := ⟦ φ ↦ 𝜎6:λ, plus(x) ↦ L_plus:λ, gt(x) ↦ L_gt:λ ⟧  # [𝑛1, 𝑛2]-    𝑛.5.1 := 𝑛3.5  # 𝑛-    𝑛.5.2 := 𝑛3.5  # 𝕄(𝑛.5.1)-  𝔼(L_plus)  # 𝕄(Φ.demo.a.φ)-    formation(⟦ φ ↦ 𝜎6:λ, plus(x) ↦ L_plus:λ, gt(x) ↦ L_gt:λ ⟧)  # 𝔻(Φ.a🌵11)-    𝛿1.6 := 𝔻(𝜎6:λ)  # 𝔻(ξ.ρ)-    formation(⟦ φ ↦ Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ ), plus(x) ↦ L_plus:λ, gt(x) ↦ L_gt:λ ⟧)  # 𝔻(Φ.a🌵12)-      formation(40-14-00-00-00-00-00-00:Δ:φ)  # 𝔻(Φ.a🌵12)-    𝛿2.6 := 40-14-00-00-00-00-00-00  # 𝔻(ξ.x)-    𝑛.6.1 := Φ.number( φ ↦ 𝜎7:λ )  # 𝑛-    𝑛.6.2 := ⟦ φ ↦ 𝜎7:λ, plus(x) ↦ L_plus:λ, gt(x) ↦ L_gt:λ ⟧  # 𝕄(𝑛.6.1)+𝕄(Φ.demo.a):+  𝑛·0·1 := Φ.foo( x ↦ Φ.number( φ ↦ 𝜎1:λ ) )+  𝕄(Φ.demo.a.x):+    𝑛·0·2 := Φ.number( φ ↦ 𝜎1:λ )+  𝕄(Φ.demo.a.φ):+    𝑛·0·3 := Φ.number( φ ↦ 𝜎1:λ )+    𝑛·0·4 := Φ.number( φ ↦ 𝜎1:λ )+    𝑛·0·5 := Φ.bytes( φ ↦ 00-00-00-00-00-00-00-00:Δ )+    𝑛·0·6 := Φ.number( φ ↦ 𝑛·0·5 )+    𝑛·0·7 := Φ.number( φ ↦ 𝜎1:λ )+    𝑛·0·8 := 𝑛·0·7.gt( x ↦ 𝑛·0·6 )+    𝔼(L_gt):+      𝔻(Φ.a🌵0):+        𝕄(Φ.a🌵0):+          𝑛·1·1 := Φ.number( φ ↦ 𝜎1:λ )+      𝛿1·1 := 𝔻(𝜎1:λ)  # 𝔻(ξ.ρ)+      𝔻(Φ.a🌵1):+        𝕄(Φ.a🌵1):+          𝑛·1·2 := Φ.number( φ ↦ 𝑛·0·5 )+          𝑛·1·3 := Φ.bytes( φ ↦ 00-00-00-00-00-00-00-00:Δ )+        𝛿·1·1 := 00-00-00-00-00-00-00-00  # 0.0+      𝛿2·1 := 𝛿·1·1  # 𝔻(ξ.x)+      𝑛·1·4 := Φ.bool( if(then, else) ↦ ⟦ λ ⤍ L_fork, φ ↦ 𝜎2:λ ⟧ )  # 𝑛+      𝕄(𝑛·1·4):+        𝑛·1·5 := Φ.bool( if(then, else) ↦ ⟦ λ ⤍ L_fork, φ ↦ 𝜎2:λ ⟧ )+      𝑛·1·6 := 𝑛·1·5  # 𝕄(𝑛·1·4)+    𝑛·0·9 := Φ.number( φ ↦ 𝜎1:λ )+    𝑛·0·10 := Φ.number( φ ↦ 𝜎1:λ )+    𝑛·0·11 := Φ.number( φ ↦ 𝜎1:λ )+    𝑛·0·12 := Φ.number( φ ↦ 𝜎1:λ )+    𝑛·0·13 := Φ.bytes( φ ↦ 3F-F0-00-00-00-00-00-00:Δ )+    𝑛·0·14 := Φ.number( φ ↦ 𝑛·0·13 )+    𝑛·0·15 := Φ.number( φ ↦ 𝜎1:λ )+    𝑛·0·16 := 𝑛·0·15.plus( x ↦ 𝑛·0·14 )+    𝔼(L_plus):+      𝔻(Φ.a🌵2):+        𝕄(Φ.a🌵2):+          𝑛·2·1 := Φ.number( φ ↦ 𝜎1:λ )+      𝛿1·2 := 𝔻(𝜎1:λ)  # 𝔻(ξ.ρ)+      𝔻(Φ.a🌵3):+        𝕄(Φ.a🌵3):+          𝑛·2·2 := Φ.number( φ ↦ 𝑛·0·13 )+          𝑛·2·3 := Φ.bytes( φ ↦ 3F-F0-00-00-00-00-00-00:Δ )+        𝛿·2·1 := 3F-F0-00-00-00-00-00-00  # 1.0+      𝛿2·2 := 𝛿·2·1  # 𝔻(ξ.x)+      𝑛·2·4 := Φ.number( φ ↦ 𝜎3:λ )  # 𝑛+      𝕄(𝑛·2·4):+        𝑛·2·5 := Φ.number( φ ↦ 𝜎3:λ )+      𝑛·2·6 := 𝑛·2·5  # 𝕄(𝑛·2·4)+    𝑛·0·17 := Φ.number( φ ↦ 𝜎1:λ )+    𝑛·0·18 := 𝑛·0·17.plus( x ↦ 𝑛·2·5 )+    𝔼(L_plus):+      𝔻(Φ.a🌵4):+        𝕄(Φ.a🌵4):+          𝑛·3·1 := Φ.number( φ ↦ 𝜎1:λ )+      𝛿1·3 := 𝔻(𝜎1:λ)  # 𝔻(ξ.ρ)+      𝛿2·3 := 𝔻(𝜎3:λ)  # 𝔻(ξ.x)+      𝑛·3·2 := Φ.number( φ ↦ 𝜎4:λ )  # 𝑛+      𝕄(𝑛·3·2):+        𝑛·3·3 := Φ.number( φ ↦ 𝜎4:λ )+      𝑛·3·4 := 𝑛·3·3  # 𝕄(𝑛·3·2)+    𝑛·0·19 := ⟦ λ ⤍ L_fork, then ↦ ∅, else ↦ ∅, φ ↦ 𝜎2:λ ⟧( then ↦ 𝑛·3·3 )+    𝑛·0·20 := Φ.number( φ ↦ 𝜎1:λ )+    𝑛·0·21 := Φ.number( φ ↦ 𝜎1:λ )+    𝑛·0·22 := Φ.number( φ ↦ 𝜎1:λ )+    𝑛·0·23 := Φ.number( φ ↦ 𝜎1:λ )+    𝑛·0·24 := 𝑛·0·23.plus( x ↦ 𝑛·0·23 )+    𝔼(L_plus):+      𝔻(Φ.a🌵6):+        𝕄(Φ.a🌵6):+          𝑛·4·1 := Φ.number( φ ↦ 𝜎1:λ )+      𝛿1·4 := 𝔻(𝜎1:λ)  # 𝔻(ξ.ρ)+      𝔻(Φ.a🌵7):+        𝕄(Φ.a🌵7):+          𝑛·4·2 := Φ.number( φ ↦ 𝜎1:λ )+      𝛿2·4 := 𝔻(𝜎1:λ)  # 𝔻(ξ.x)+      𝑛·4·3 := Φ.number( φ ↦ 𝜎5:λ )  # 𝑛+      𝕄(𝑛·4·3):+        𝑛·4·4 := Φ.number( φ ↦ 𝜎5:λ )+      𝑛·4·5 := 𝑛·4·4  # 𝕄(𝑛·4·3)+    𝑛·0·25 := ⟦ λ ⤍ L_fork, then ↦ ∅, else ↦ ∅, φ ↦ 𝜎2:λ ⟧( then ↦ 𝑛·3·3 )+    𝑛·0·26 := 𝑛·0·25( else ↦ 𝑛·4·4 )+    𝔼(L_fork):+      𝛿1·5 := 𝔻(𝜎2:λ)  # 𝔻(ξ.φ)+      𝑛1·5 := 𝑛·3·4  # 𝕄(ξ.then)+      𝑛2·5 := 𝑛·4·5  # 𝕄(ξ.else)+      𝔻(𝜎6:λ) ∈ { 𝔻(𝜎4:λ), 𝔻(𝜎5:λ) }+      𝑛3·5 := ⟦ φ ↦ 𝜎6:λ, plus(x) ↦ L_plus:λ, gt(x) ↦ L_gt:λ ⟧  # [𝑛1, 𝑛2]+      𝑛·5·1 := 𝑛3·5  # 𝑛+      𝑛·5·2 := 𝑛3·5  # 𝕄(𝑛·5·1)+    𝑛·0·27 := Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )+    𝑛·0·28 := Φ.number( φ ↦ 𝑛·0·27 )+    𝑛·0·29 := Φ.number( φ ↦ 𝜎6:λ ).plus( x ↦ 𝑛·0·28 )+    𝔼(L_plus):+      𝔻(Φ.a🌵11):+        𝕄(Φ.a🌵11):+          𝑛·6·1 := Φ.number( φ ↦ 𝜎6:λ )+      𝛿1·6 := 𝔻(𝜎6:λ)  # 𝔻(ξ.ρ)+      𝔻(Φ.a🌵12):+        𝕄(Φ.a🌵12):+          𝑛·6·2 := Φ.number( φ ↦ 𝑛·0·27 )+          𝑛·6·3 := Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )+        𝛿·6·1 := 40-14-00-00-00-00-00-00  # 5.0+      𝛿2·6 := 𝛿·6·1  # 𝔻(ξ.x)+      𝑛·6·4 := Φ.number( φ ↦ 𝜎7:λ )  # 𝑛+      𝕄(𝑛·6·4):+        𝑛·6·5 := Φ.number( φ ↦ 𝜎7:λ )+      𝑛·6·6 := 𝑛·6·5  # 𝕄(𝑛·6·4) ```  <!-- markdownlint-enable MD013 -->@@ -756,11 +863,11 @@ would be minted and never consumed, and `foo` would read as a program that computes a condition, computes both branches and then drops the branch point. -All six firings stand under `Φ.demo.a.φ`, which is as near as a locator gets-to any of them: the walk entered the `φ` of the formation `Φ.demo.a` morphs to,-and everything under it — the dispatches of the chain, the arguments of `if` —-stands under no attribute of any formation, so the binding the walk had entered-is what the protocol writes them under.+All six firings stand in the block `𝕄(Φ.demo.a.φ):`, which is as near as a+locator gets to any of them: the walk entered the `φ` of the formation+`Φ.demo.a` morphs to, and everything under it — the dispatches of the chain,+the arguments of `if` — stands under no attribute of any formation, so the+binding the walk had entered is what the protocol writes them under.  A firing that happened while an operand of another was being reduced stands one level deeper, under the firing that asked for it. Here it never happens,@@ -782,51 +889,64 @@     --sweet --hide-rho sum.phi $ cat atoms.xml <?xml version="1.0" encoding="UTF-8"?>-<dataize at="Φ">-  <formation at="Φ" term="⟦ bytes(φ) ↦ ⟦⟧, number(φ) ↦ ⟦ plus(x) ↦ L_number_plus:λ ⟧, φ ↦ 5.plus( 6 ) ⟧">-    <applied meta="𝑛.0.1" by="morph" at="Φ" of="Φ.number"><attr name="φ">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>-    <applied meta="𝑛.0.2" by="morph" at="Φ" of="𝑛.0.1.plus"><attr name="x">6</attr></applied>+<protocol>+  <dataize at="Φ">+    <morph at="Φ">+      <applied meta="𝑛·0·1" by="morph" at="Φ" of="Φ.number"><attr name="φ">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>+      <applied meta="𝑛·0·2" by="morph" at="Φ" of="𝑛·0·1.plus"><attr name="x">6</attr></applied>+    </morph>     <evaluate λ="L_number_plus" by="dataize" at="Φ">-      <applied meta="𝑛.1.1" by="morph" at="Φ.a🌵0" of="Φ.number"><attr name="φ">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>-      <formation at="Φ.a🌵0" term="𝑛.1.1">-        <applied meta="𝑛.1.2" by="morph" at="Φ.a🌵0" of="Φ.bytes"><attr name="φ">40-14-00-00-00-00-00-00:Δ</attr></applied>-        <formation at="Φ.a🌵0" term="𝑛.1.2">-        </formation>-      </formation>-      <bind meta="𝛿1.1">40-14-00-00-00-00-00-00</bind>-      <applied meta="𝑛.1.3" by="morph" at="Φ.a🌵1" of="Φ.number"><attr name="φ">Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )</attr></applied>-      <formation at="Φ.a🌵1" term="𝑛.1.3">-        <applied meta="𝑛.1.4" by="morph" at="Φ.a🌵1" of="Φ.bytes"><attr name="φ">40-18-00-00-00-00-00-00:Δ</attr></applied>-        <formation at="Φ.a🌵1" term="𝑛.1.4">-        </formation>-      </formation>-      <bind meta="𝛿2.1">40-18-00-00-00-00-00-00</bind>+      <dataize at="Φ.a🌵0">+        <morph at="Φ.a🌵0">+          <applied meta="𝑛·1·1" by="morph" at="Φ.a🌵0" of="Φ.number"><attr name="φ">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>+          <applied meta="𝑛·1·2" by="morph" at="Φ.a🌵0" of="Φ.bytes"><attr name="φ">40-14-00-00-00-00-00-00:Δ</attr></applied>+        </morph>+        <delta meta="𝛿·1·1" number="5.0">40-14-00-00-00-00-00-00</delta>+      </dataize>+      <bind meta="𝛿1·1">𝛿·1·1</bind>+      <dataize at="Φ.a🌵1">+        <morph at="Φ.a🌵1">+          <applied meta="𝑛·1·3" by="morph" at="Φ.a🌵1" of="Φ.number"><attr name="φ">Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )</attr></applied>+          <applied meta="𝑛·1·4" by="morph" at="Φ.a🌵1" of="Φ.bytes"><attr name="φ">40-18-00-00-00-00-00-00:Δ</attr></applied>+        </morph>+        <delta meta="𝛿·1·2" number="6.0">40-18-00-00-00-00-00-00</delta>+      </dataize>+      <bind meta="𝛿2·1">𝛿·1·2</bind>       <minted symbol="𝜎1">40-14-00-00-00-00-00-00 40-18-00-00-00-00-00-00</minted>-      <built meta="𝑛.1.5">Φ.number( φ ↦ 𝜎1:λ )</built>-      <applied meta="𝑛.1.6" by="morph" at="Φ" of="Φ.number"><attr name="φ">𝜎1</attr></applied>-      <answer meta="𝑛.1.7">𝑛.1.6</answer>+      <built meta="𝑛·1·5">Φ.number( φ ↦ 𝜎1:λ )</built>+      <morph at="𝑛·1·5">+        <applied meta="𝑛·1·6" by="morph" at="𝑛·1·5" of="Φ.number"><attr name="φ">𝜎1</attr></applied>+      </morph>+      <answer meta="𝑛·1·7">𝑛·1·6</answer>     </evaluate>-    <formation at="Φ" term="𝑛.1.6">-    </formation>-  </formation>-</dataize>+  </dataize>+</protocol> ```  <!-- markdownlint-enable MD013 --> -The root is the run itself, named after the judgment it ran — `<dataize>` for a-𝔻, `<morph>` for a 𝕄 — with `at` naming the term it was aimed at, which is-what the text format opens with as `𝔻(Φ)`. `<evaluate>` is one firing of 𝔼, `λ`-naming the entry that answered it, `by` naming the judgment that asked for the-firing — the same word the root is named after and an `<unanswered>` carries —-and `at` naming the site it was fired at. The text format writes those two as-the comment of its line, `𝔻(Φ)`.-`<formation at="Φ" term="⟦ … ⟧">` is a formation 𝔻 got into through `box`,-which the text format writes as `formation(⟦ … ⟧)  # 𝔻(Φ)`: `at` names the-site it was entered at and `term` holds the formation. Whatever the `φ` body-does is written inside the element, so it closes where the text format drops-back to the indentation it opened at, and like the text line it counts nothing-and names no meta.+The root is `<protocol>`, and the run stands inside it, named after the+judgment it ran — `<dataize>` for a 𝔻, `<morph>` for a 𝕄 — with `at` naming+the term it was aimed at, which is what the text format opens with as `𝔻(Φ)`.+After the run the root holds `<msec>`, `<firings>` and `<fps>`: how long the+run took, how many λ functions it fired, and how many it fired per second. The+text format ends with the same three as `msec(…)`, `firings(…)` and `fps(…)`.+The examples here leave them out, since the time differs from run to run.+`<evaluate>` is one firing of 𝔼, `λ` naming the entry that answered it, `by`+naming the judgment that asked for the firing — the same word the run is named+after and an `<unanswered>` carries —+and `at` naming the site it was fired at. The text format leaves those two to+the block the firing stands in, `𝔻(Φ):`, while the markup keeps them on every+element, so a program reading it never has to track the elements around one.+A nested `<dataize at="Φ.a🌵0">` or `<morph at="Φ.a🌵0">` is a judgment started+at a new site, which the text format writes as `𝔻(Φ.a🌵0):` or `𝕄(Φ.a🌵0):`,+and `at` names that site. Whatever the judgment does is written inside the+element, so it closes where the text format drops back to the indentation it+opened at, and like the text line it counts nothing and names no meta.+`<delta>` is the datum the `delta` rule found, `meta` naming it the way the+text format does, and the `<bind>` after the element holds that name in place+of the data. A datum of eight bytes also carries `number`, the double the text+format writes as the comment of its line. `<bind>` is one meta the firing bound, `meta` naming it the same way the text format names it, counter and all, and the element holding the value it took: a term where the operand was reduced with 𝕄, the datum itself where a `dataize`@@ -834,9 +954,9 @@ `dataize` operand may come to, the datum manufactured for an unknown, and holds the formation that unknown names rather than the 42 standing for it: a `𝜎` is the name of a λ function and no term of its own, so what 𝔻 was applied to is-`𝜎2:λ` and never `𝜎2` alone. It carries `meta` where the root carries+`𝜎2:λ` and never `𝜎2` alone. It carries `meta` where the run carries `at`, the same difference the text format draws between `𝔻(Φ)` at the top-and `𝛿1.2 := 𝔻(…)` in a block. The name of the element is what tells a+and `𝛿1·2 := 𝔻(…)` in a block. The name of the element is what tells a manufactured datum from data, the way `𝔻(…)` does in the text format, so nothing has to be read off the presence of an attribute. `<answer>` holds the term the firing answered with, named the same way by its own `meta`, and@@ -844,9 +964,9 @@ of: two elements rather than two attributes of one, for the same reason `<dataize>` is no `<bind>`. -`<applied meta="𝑛.1.6" by="morph" at="Φ" of="Φ.number">` is an object an-application made, which the text format writes as-`applied(𝑛.1.6) := …  # 𝕄(Φ)`: `meta` names the object the way the text format+`<applied meta="𝑛·1·6" by="morph" at="𝑛·1·5" of="Φ.number">` is an object an+application made, which the text format writes as `𝑛·1·6 := …` in the block+`𝕄(𝑛·1·5):`: `meta` names the object the way the text format does, counted with the `<built>` and the `<answer>` of the firing it stands in, `by` and `at` name the judgment that normalized and the site it stood at, and `of` names the object applied, the way `<deferred>` and `<looped>` name it.@@ -854,8 +974,8 @@ the text holding the name of the object or the application it is, the symbol, such as `𝜎1`, where it is a bare one, and the term itself otherwise. A later element holding that object holds its name instead, in its text or in its-`term`, so `<answer meta="𝑛.1.7">𝑛.1.6</answer>` says the firing answered with-it and `<formation at="Φ" term="𝑛.1.6">` that 𝔻 got into it.+`term`, so `<answer meta="𝑛·1·7">𝑛·1·6</answer>` says the firing answered with+it and `<dataize at="Φ">` that 𝔻 got into it.  `<known symbol="𝜎44">3F-F0-00-00-00-00-00-00</known>` is the fact a `symbolize` line writes about a symbol it minted, which the text format writes as@@ -883,7 +1003,7 @@ lists its pair. With the `λ` of the block the element reads as the fact `𝔻(𝜎1:λ) == L_number_plus(40-14-…, 40-18-…)`, and a firing of an entry with no `dataize` line writes `<minted symbol="𝜎1"/>`. The symbol is also the edge-a reader joins on: a later `<dataize meta="𝛿1.5">𝜎2:λ</dataize>` names the+a reader joins on: a later `<dataize meta="𝛿1·5">𝜎2:λ</dataize>` names the symbol the firing that wrote `<minted symbol="𝜎2">` handed out. A firing minting two symbols writes two elements and one minting none writes none, which no attribute on the answer could say: a term may carry several symbols,@@ -910,33 +1030,39 @@ [ERROR]: No entry of --symbolic answers the λ function 'L_number_nope' $ cat atoms.xml <?xml version="1.0" encoding="UTF-8"?>-<dataize at="Φ">-  <formation at="Φ" term="⟦ bytes(φ) ↦ ⟦⟧, number(φ) ↦ ⟦ plus(x) ↦ L_number_plus:λ, nope ↦ L_number_nope:λ ⟧, φ ↦ 5.plus( 6 ).nope ⟧">-    <applied meta="𝑛.0.1" by="morph" at="Φ" of="Φ.number"><attr name="φ">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>-    <applied meta="𝑛.0.2" by="morph" at="Φ" of="𝑛.0.1.plus"><attr name="x">6</attr></applied>-    <evaluate λ="L_number_plus" by="morph" at="Φ">-      <applied meta="𝑛.1.1" by="morph" at="Φ.a🌵0" of="Φ.number"><attr name="φ">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>-      <formation at="Φ.a🌵0" term="𝑛.1.1">-        <applied meta="𝑛.1.2" by="morph" at="Φ.a🌵0" of="Φ.bytes"><attr name="φ">40-14-00-00-00-00-00-00:Δ</attr></applied>-        <formation at="Φ.a🌵0" term="𝑛.1.2">-        </formation>-      </formation>-      <bind meta="𝛿1.1">40-14-00-00-00-00-00-00</bind>-      <applied meta="𝑛.1.3" by="morph" at="Φ.a🌵1" of="Φ.number"><attr name="φ">Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )</attr></applied>-      <formation at="Φ.a🌵1" term="𝑛.1.3">-        <applied meta="𝑛.1.4" by="morph" at="Φ.a🌵1" of="Φ.bytes"><attr name="φ">40-18-00-00-00-00-00-00:Δ</attr></applied>-        <formation at="Φ.a🌵1" term="𝑛.1.4">-        </formation>-      </formation>-      <bind meta="𝛿2.1">40-18-00-00-00-00-00-00</bind>-      <minted symbol="𝜎1">40-14-00-00-00-00-00-00 40-18-00-00-00-00-00-00</minted>-      <built meta="𝑛.1.5">Φ.number( φ ↦ 𝜎1:λ )</built>-      <applied meta="𝑛.1.6" by="morph" at="Φ" of="Φ.number"><attr name="φ">𝜎1</attr></applied>-      <answer meta="𝑛.1.7">𝑛.1.6</answer>-    </evaluate>+<protocol>+  <dataize at="Φ">+    <morph at="Φ">+      <applied meta="𝑛·0·1" by="morph" at="Φ" of="Φ.number"><attr name="φ">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>+      <applied meta="𝑛·0·2" by="morph" at="Φ" of="𝑛·0·1.plus"><attr name="x">6</attr></applied>+      <evaluate λ="L_number_plus" by="morph" at="Φ">+        <dataize at="Φ.a🌵0">+          <morph at="Φ.a🌵0">+            <applied meta="𝑛·1·1" by="morph" at="Φ.a🌵0" of="Φ.number"><attr name="φ">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>+            <applied meta="𝑛·1·2" by="morph" at="Φ.a🌵0" of="Φ.bytes"><attr name="φ">40-14-00-00-00-00-00-00:Δ</attr></applied>+          </morph>+          <delta meta="𝛿·1·1" number="5.0">40-14-00-00-00-00-00-00</delta>+        </dataize>+        <bind meta="𝛿1·1">𝛿·1·1</bind>+        <dataize at="Φ.a🌵1">+          <morph at="Φ.a🌵1">+            <applied meta="𝑛·1·3" by="morph" at="Φ.a🌵1" of="Φ.number"><attr name="φ">Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )</attr></applied>+            <applied meta="𝑛·1·4" by="morph" at="Φ.a🌵1" of="Φ.bytes"><attr name="φ">40-18-00-00-00-00-00-00:Δ</attr></applied>+          </morph>+          <delta meta="𝛿·1·2" number="6.0">40-18-00-00-00-00-00-00</delta>+        </dataize>+        <bind meta="𝛿2·1">𝛿·1·2</bind>+        <minted symbol="𝜎1">40-14-00-00-00-00-00-00 40-18-00-00-00-00-00-00</minted>+        <built meta="𝑛·1·5">Φ.number( φ ↦ 𝜎1:λ )</built>+        <morph at="𝑛·1·5">+          <applied meta="𝑛·1·6" by="morph" at="𝑛·1·5" of="Φ.number"><attr name="φ">𝜎1</attr></applied>+        </morph>+        <answer meta="𝑛·1·7">𝑛·1·6</answer>+      </evaluate>+    </morph>     <unanswered λ="L_number_nope" by="dataize">L_number_nope:λ</unanswered>-  </formation>-</dataize>+  </dataize>+</protocol> ```  <!-- markdownlint-enable MD013 -->@@ -968,8 +1094,8 @@ $ phino dataize --locator=Q.t --protocol=wide.txt --abridged --quiet \     --sweet --hide-rho wide.phi $ cat wide.txt-𝔻(Φ.t)-  formation(⟦ φ ↦ 48-65-6C-6C-6F-2C-20-77-6F-72-6C-64:Δ, +3 ⟧)  # 𝔻(Φ.t)+𝔻(Φ.t):+  𝛿·0·1 := 48-65-6C-6C-6F-2C-20-77-6F-72-6C-64 ```  <!-- markdownlint-enable MD013 -->@@ -985,8 +1111,8 @@ $ phino dataize --locator=Q.t --protocol=wide.txt --abridged \     --abridged-data --quiet --sweet --hide-rho wide.phi $ cat wide.txt-𝔻(Φ.t)-  formation(⟦ φ ↦ 48-65-..(8b)..-6C-64:Δ, +3 ⟧)  # 𝔻(Φ.t)+𝔻(Φ.t):+  𝛿·0·1 := 48-65-..(8b)..-6C-64 ```  <!-- markdownlint-enable MD013 -->@@ -1054,26 +1180,44 @@ $ phino dataize --symbolic=atoms.yaml --partial --protocol=atoms.txt --quiet \     --sweet --hide-rho partial.phi $ cat atoms.txt-𝔻(Φ)-  formation(⟦ bytes(φ) ↦ ⟦⟧, number(φ) ↦ ⟦ plus(x) ↦ L_number_plus:λ, times(x) ↦ L_number_times:λ, as-bool ↦ L_number_as_bool:λ ⟧, φ ↦ 2.times( 3 ).plus( 4 ).as-bool ⟧)  # 𝔻(Φ)-    𝔼(L_number_times)  # 𝕄(Φ)-      formation(⟦ φ ↦ Φ.bytes( φ ↦ 40-00-00-00-00-00-00-00:Δ ), plus(x) ↦ L_number_plus:λ, times(x) ↦ L_number_times:λ, as-bool ↦ L_number_as_bool:λ ⟧)  # 𝔻(Φ.a🌵0)-        formation(40-00-00-00-00-00-00-00:Δ:φ)  # 𝔻(Φ.a🌵0)-      𝛿1.1 := 40-00-00-00-00-00-00-00  # 𝔻(ξ.ρ)-      formation(⟦ φ ↦ Φ.bytes( φ ↦ 40-08-00-00-00-00-00-00:Δ ), plus(x) ↦ L_number_plus:λ, times(x) ↦ L_number_times:λ, as-bool ↦ L_number_as_bool:λ ⟧)  # 𝔻(Φ.a🌵1)-        formation(40-08-00-00-00-00-00-00:Δ:φ)  # 𝔻(Φ.a🌵1)-      𝛿2.1 := 40-08-00-00-00-00-00-00  # 𝔻(ξ.x)-      𝑛.1.1 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛-      𝑛.1.2 := ⟦ φ ↦ 𝜎1:λ, plus(x) ↦ L_number_plus:λ, times(x) ↦ L_number_times:λ, as-bool ↦ L_number_as_bool:λ ⟧  # 𝕄(𝑛.1.1)-    𝔼(L_number_plus)  # 𝕄(Φ)-      formation(⟦ φ ↦ 𝜎1:λ, plus(x) ↦ L_number_plus:λ, times(x) ↦ L_number_times:λ, as-bool ↦ L_number_as_bool:λ ⟧)  # 𝔻(Φ.a🌵2)-      𝛿1.2 := 𝔻(𝜎1:λ)  # 𝔻(ξ.ρ)-      formation(⟦ φ ↦ Φ.bytes( φ ↦ 40-10-00-00-00-00-00-00:Δ ), plus(x) ↦ L_number_plus:λ, times(x) ↦ L_number_times:λ, as-bool ↦ L_number_as_bool:λ ⟧)  # 𝔻(Φ.a🌵3)-        formation(40-10-00-00-00-00-00-00:Δ:φ)  # 𝔻(Φ.a🌵3)-      𝛿2.2 := 40-10-00-00-00-00-00-00  # 𝔻(ξ.x)-      𝑛.2.1 := Φ.number( φ ↦ 𝜎2:λ )  # 𝑛-      𝑛.2.2 := ⟦ φ ↦ 𝜎2:λ, plus(x) ↦ L_number_plus:λ, times(x) ↦ L_number_times:λ, as-bool ↦ L_number_as_bool:λ ⟧  # 𝕄(𝑛.2.1)-    unanswered(L_number_as_bool)  # 𝔻(L_number_as_bool:λ)+𝔻(Φ):+  𝕄(Φ):+    𝑛·0·1 := 2+    𝑛·0·2 := 𝑛·0·1.times( x ↦ 3 )+    𝔼(L_number_times):+      𝔻(Φ.a🌵0):+        𝕄(Φ.a🌵0):+          𝑛·1·1 := 2+          𝑛·1·2 := Φ.bytes( φ ↦ 40-00-00-00-00-00-00-00:Δ )+        𝛿·1·1 := 40-00-00-00-00-00-00-00  # 2.0+      𝛿1·1 := 𝛿·1·1  # 𝔻(ξ.ρ)+      𝔻(Φ.a🌵1):+        𝕄(Φ.a🌵1):+          𝑛·1·3 := 3+          𝑛·1·4 := Φ.bytes( φ ↦ 40-08-00-00-00-00-00-00:Δ )+        𝛿·1·2 := 40-08-00-00-00-00-00-00  # 3.0+      𝛿2·1 := 𝛿·1·2  # 𝔻(ξ.x)+      𝑛·1·5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛+      𝕄(𝑛·1·5):+        𝑛·1·6 := Φ.number( φ ↦ 𝜎1:λ )+      𝑛·1·7 := 𝑛·1·6  # 𝕄(𝑛·1·5)+    𝑛·0·3 := 𝑛·1·6.plus( x ↦ 4 )+    𝔼(L_number_plus):+      𝔻(Φ.a🌵2):+        𝕄(Φ.a🌵2):+          𝑛·2·1 := Φ.number( φ ↦ 𝜎1:λ )+      𝛿1·2 := 𝔻(𝜎1:λ)  # 𝔻(ξ.ρ)+      𝔻(Φ.a🌵3):+        𝕄(Φ.a🌵3):+          𝑛·2·2 := 4+          𝑛·2·3 := Φ.bytes( φ ↦ 40-10-00-00-00-00-00-00:Δ )+        𝛿·2·1 := 40-10-00-00-00-00-00-00  # 4.0+      𝛿2·2 := 𝛿·2·1  # 𝔻(ξ.x)+      𝑛·2·4 := Φ.number( φ ↦ 𝜎2:λ )  # 𝑛+      𝕄(𝑛·2·4):+        𝑛·2·5 := Φ.number( φ ↦ 𝜎2:λ )+      𝑛·2·6 := 𝑛·2·5  # 𝕄(𝑛·2·4)+  unanswered(L_number_as_bool)  # 𝔻(L_number_as_bool:λ) ```  <!-- markdownlint-enable MD013 -->@@ -1136,7 +1280,7 @@     --protocol=split.txt --sweet --flat split.phi [ERROR]: Evaluation did not finish before reaching the limit of seconds: --max-seconds=5 $ grep -o 'timeout.*' split.txt-timeout(5)  # 𝕄(Φ.a🌵14250)+timeout(5) ```  ## Morph@@ -1275,9 +1419,9 @@ $ phino morph --deep --locator=Q.y --protocol=p.txt --sweet --hide-rho box.phi 𝜎2:λ $ head -3 p.txt-𝕄(Φ.y)-  applied(𝑛.0.1) := Φ.box( x ↦ 𝜎1:λ )  # 𝕄(Φ.y)-  deferred(𝜎2) := Φ.box( x ↦ 𝜎1:λ )  # 𝕄(Φ.y)+𝕄(Φ.y):+  𝑛·0·1 := Φ.box( x ↦ 𝜎1:λ )+  deferred(𝜎2) := Φ.box( x ↦ 𝜎1:λ ) ```  ### Acyclic morphing@@ -1356,7 +1500,9 @@ `n ↦ 3` and then with `n ↦ 2` is two formations, so a recursion over data is not cut while it goes on computing. Take a factorial over a symbolic argument, with `fact.yaml` answering `L_zero`, `L_dec` and `L_mul` with a fresh symbol-each and `L_if` a fork joining its two branches:+each and `L_if` a fork joining its two branches. The argument, and what `L_dec`+answers, is an object whose `φ` is a symbol rather than a bare symbol, since+the walk of `--deep` defers a copy over a bare symbol instead of entering it:  <!-- markdownlint-disable MD013 --> @@ -1368,7 +1514,7 @@   dec ↦ ⟦ x ↦ ∅, λ ⤍ L_dec ⟧,   mul ↦ ⟦ a ↦ ∅, b ↦ ∅, λ ⤍ L_mul ⟧,   fact ↦ ⟦ n ↦ ∅, φ ↦ Φ.if( c ↦ Φ.zero( x ↦ ξ.n ), left ↦ ⟦ Δ ⤍ 01- ⟧, right ↦ Φ.mul( a ↦ ξ.n, b ↦ Φ.fact( n ↦ Φ.dec( x ↦ ξ.n ) ) ) ) ⟧,-  x ↦ Φ.fact( n ↦ ⟦ λ ⤍ 𝜎1 ⟧ )+  x ↦ Φ.fact( n ↦ ⟦ φ ↦ ⟦ λ ⤍ 𝜎1 ⟧ ⟧ ) ⟧ $ cat fact.yaml - λ: L_zero@@ -1378,7 +1524,7 @@ - λ: L_dec   dataize:     𝛿1: $.x-  𝑛: ⟦ λ ⤍ 𝜎 ⟧+  𝑛: ⟦ φ ↦ ⟦ λ ⤍ 𝜎 ⟧ ⟧ - λ: L_mul   dataize:     𝛿1: $.a@@ -1398,95 +1544,141 @@   𝑛: 𝑛5 $ phino morph --deep --acyclic=proven --partial --sweet --hide-rho --flat \     --symbolic=fact.yaml --locator='Q.x' --protocol=fact.txt fact.phi-⟦ n ↦ 𝜎1:λ, φ ↦ Φ.if( c ↦ 𝜎2:λ, left ↦ 01-:Δ, right ↦ Φ.mul( a ↦ n, b ↦ Φ.fact( n ↦ 𝜎3:λ ) ) ) ⟧+⟦ n ↦ 𝜎1:λ:φ, φ ↦ Φ.if( c ↦ 𝜎2:λ, left ↦ 01-:Δ, right ↦ Φ.mul( a ↦ n, b ↦ Φ.fact( n ↦ 𝜎3:λ:φ ) ) ) ⟧ $ cat fact.txt-𝕄(Φ.x)-  𝔼(L_zero)  # 𝕄(Φ.x.φ)-    𝛿1.1 := 𝔻(𝜎1:λ)  # 𝔻(ξ.x)-    𝑛.1.1 := 𝜎2:λ  # 𝑛-    𝑛.1.2 := 𝜎2:λ  # 𝕄(𝑛.1.1)-  𝔼(L_dec)  # 𝕄(Φ.x.φ)-    𝛿1.2 := 𝔻(𝜎1:λ)  # 𝔻(ξ.x)-    𝑛.2.1 := 𝜎3:λ  # 𝑛-    𝑛.2.2 := 𝜎3:λ  # 𝕄(𝑛.2.1)-  𝔼(L_mul)  # 𝕄(Φ.x.φ)-    𝛿1.3 := 𝔻(𝜎1:λ)  # 𝔻(ξ.a)-    formation(⟦ n ↦ 𝜎3:λ, φ ↦ Φ.if( c ↦ Φ.zero( x ↦ n ), left ↦ 01-:Δ, right ↦ Φ.mul( a ↦ n, b ↦ Φ.fact( n ↦ Φ.dec( x ↦ n ) ) ) ) ⟧)  # 𝔻(Φ.a🌵3)-      𝔼(L_if)  # 𝔻(Φ.a🌵3)-        𝔼(L_zero)  # 𝔻(Φ.a🌵4)-          𝛿1.5 := 𝔻(𝜎3:λ)  # 𝔻(ξ.x)-          𝑛.5.1 := 𝜎4:λ  # 𝑛-          𝑛.5.2 := 𝜎4:λ  # 𝕄(𝑛.5.1)-        𝛿1.4 := 𝔻(𝜎4:λ)  # 𝔻(ξ.c)-        𝑛1.4 := 01-:Δ  # 𝕄(ξ.left)-        𝔼(L_dec)  # 𝕄(Φ.a🌵7.b)-          𝛿1.6 := 𝔻(𝜎3:λ)  # 𝔻(ξ.x)-          𝑛.6.1 := 𝜎5:λ  # 𝑛-          𝑛.6.2 := 𝜎5:λ  # 𝕄(𝑛.6.1)-        looped(⟦ a ↦ 𝜎1:λ, b ↦ Φ.fact( n ↦ 𝜎3:λ ), λ ⤍ L_mul ⟧)  # 𝕄(Φ.a🌵7), proven-        𝑛2.4 := ⟦ a ↦ 𝜎3:λ, b ↦ Φ.fact( n ↦ 𝜎5:λ ), λ ⤍ L_mul ⟧  # 𝕄(ξ.right)-        𝔻(𝜎6:λ) == 01--        𝑛3.4 := 𝜎6:λ  # 𝑛1-        𝑛4.4 := ⟦ a ↦ 𝜎3:λ, b ↦ Φ.fact( n ↦ 𝜎5:λ ), λ ⤍ L_mul ⟧  # 𝑛2-        stuck(L_if)-    stuck(L_if)-  𝔼(L_if)  # 𝕄(Φ.x.φ)-    𝛿1.7 := 𝔻(𝜎2:λ)  # 𝔻(ξ.c)-    𝑛1.7 := 01-:Δ  # 𝕄(ξ.left)-    𝔼(L_mul)  # 𝕄(Φ.a🌵11)-      𝛿1.8 := 𝔻(𝜎1:λ)  # 𝔻(ξ.a)-      formation(⟦ n ↦ 𝜎3:λ, φ ↦ Φ.if( c ↦ Φ.zero( x ↦ n ), left ↦ 01-:Δ, right ↦ Φ.mul( a ↦ n, b ↦ Φ.fact( n ↦ Φ.dec( x ↦ n ) ) ) ) ⟧)  # 𝔻(Φ.a🌵13)-        𝔼(L_if)  # 𝔻(Φ.a🌵13)-          𝔼(L_zero)  # 𝔻(Φ.a🌵14)-            𝛿1.10 := 𝔻(𝜎3:λ)  # 𝔻(ξ.x)-            𝑛.10.1 := 𝑛.5.2  # 𝑛-            𝑛.10.2 := 𝑛.5.2  # 𝕄(𝑛.10.1)-          𝛿1.9 := 𝔻(𝜎4:λ)  # 𝔻(ξ.c)-          𝑛1.9 := 01-:Δ  # 𝕄(ξ.left)-          𝔼(L_dec)  # 𝕄(Φ.a🌵17.b)-            𝛿1.11 := 𝔻(𝜎3:λ)  # 𝔻(ξ.x)-            𝑛.11.1 := 𝑛.6.2  # 𝑛-            𝑛.11.2 := 𝑛.6.2  # 𝕄(𝑛.11.1)-          looped(⟦ a ↦ 𝜎1:λ, b ↦ Φ.fact( n ↦ 𝜎3:λ ), λ ⤍ L_mul ⟧)  # 𝕄(Φ.a🌵17), proven-          𝑛2.9 := ⟦ a ↦ 𝜎3:λ, b ↦ Φ.fact( n ↦ 𝜎5:λ ), λ ⤍ L_mul ⟧  # 𝕄(ξ.right)+𝕄(Φ.x):+  𝑛·0·1 := Φ.fact( n ↦ 𝜎1:λ:φ )+  𝕄(Φ.x.φ):+    𝑛·0·2 := Φ.zero( x ↦ 𝜎1:λ:φ )+    𝔼(L_zero):+      𝛿1·1 := 𝔻(𝜎1:λ)  # 𝔻(ξ.x)+      𝑛·1·1 := 𝜎2:λ  # 𝑛+      𝑛·1·2 := 𝜎2:λ  # 𝕄(𝑛·1·1)+    𝑛·0·3 := Φ.if( c ↦ 𝜎2:λ )+    𝑛·0·4 := Φ.if( c ↦ 𝜎2:λ )+    𝑛·0·5 := 𝑛·0·4( left ↦ 01-:Δ )+    𝑛·0·6 := Φ.mul( a ↦ 𝜎1:λ:φ )+    𝑛·0·7 := Φ.dec( x ↦ 𝜎1:λ:φ )+    𝔼(L_dec):+      𝛿1·2 := 𝔻(𝜎1:λ)  # 𝔻(ξ.x)+      𝑛·2·1 := 𝜎3:λ:φ  # 𝑛+      𝑛·2·2 := 𝜎3:λ:φ  # 𝕄(𝑛·2·1)+    𝑛·0·8 := Φ.fact( n ↦ 𝜎3:λ:φ )+    𝑛·0·9 := Φ.mul( a ↦ 𝜎1:λ:φ )+    𝑛·0·10 := 𝑛·0·9( b ↦ 𝑛·0·8 )+    𝔼(L_mul):+      𝛿1·3 := 𝔻(𝜎1:λ)  # 𝔻(ξ.a)+      𝔻(Φ.a🌵3):+        𝕄(Φ.a🌵3):+          𝑛·3·1 := Φ.fact( n ↦ 𝜎3:λ:φ )+          𝑛·3·2 := Φ.if( c ↦ Φ.zero( x ↦ 𝜎3:λ:φ ) )+          𝑛·3·3 := 𝑛·3·2( left ↦ 01-:Δ )+          𝑛·3·4 := 𝑛·3·3( right ↦ Φ.mul( a ↦ 𝜎3:λ:φ, b ↦ Φ.fact( n ↦ Φ.dec( x ↦ 𝜎3:λ:φ ) ) ) )+        𝔼(L_if):+          𝔻(Φ.a🌵4):+            𝕄(Φ.a🌵4):+              𝑛·4·1 := Φ.zero( x ↦ 𝜎3:λ:φ )+            𝔼(L_zero):+              𝛿1·5 := 𝔻(𝜎3:λ)  # 𝔻(ξ.x)+              𝑛·5·1 := 𝜎4:λ  # 𝑛+              𝑛·5·2 := 𝜎4:λ  # 𝕄(𝑛·5·1)+          𝛿1·4 := 𝔻(𝜎4:λ)  # 𝔻(ξ.c)+          𝑛1·4 := 01-:Δ  # 𝕄(ξ.left)+          𝕄(Φ.a🌵7):+            𝑛·4·2 := Φ.mul( a ↦ 𝜎3:λ:φ )+            𝑛·4·3 := 𝑛·4·2( b ↦ Φ.fact( n ↦ Φ.dec( x ↦ 𝜎3:λ:φ ) ) )+            𝕄(Φ.a🌵7.b):+              𝑛·4·4 := Φ.dec( x ↦ 𝜎3:λ:φ )+              𝔼(L_dec):+                𝛿1·6 := 𝔻(𝜎3:λ)  # 𝔻(ξ.x)+                𝑛·6·1 := 𝜎5:λ:φ  # 𝑛+                𝑛·6·2 := 𝜎5:λ:φ  # 𝕄(𝑛·6·1)+              𝑛·4·5 := Φ.fact( n ↦ 𝜎5:λ:φ )+            looped(𝑛·0·10)  # proven+          𝑛2·4 := 𝑛·4·3  # 𝕄(ξ.right)           𝔻(𝜎6:λ) == 01--          𝑛3.9 := 𝑛3.4  # 𝑛1-          𝑛4.9 := ⟦ a ↦ 𝜎3:λ, b ↦ Φ.fact( n ↦ 𝜎5:λ ), λ ⤍ L_mul ⟧  # 𝑛2+          𝑛3·4 := 𝜎6:λ  # 𝑛1+          𝑛4·4 := 𝑛·4·3  # 𝑛2           stuck(L_if)       stuck(L_if)-    𝑛2.7 := ⟦ a ↦ 𝜎1:λ, b ↦ Φ.fact( n ↦ 𝜎3:λ ), λ ⤍ L_mul ⟧  # 𝕄(ξ.right)-    𝔻(𝜎4:λ) == 01--    𝑛3.7 := 𝑛.10.2  # 𝑛1-    𝑛4.7 := ⟦ a ↦ 𝜎1:λ, b ↦ Φ.fact( n ↦ 𝜎3:λ ), λ ⤍ L_mul ⟧  # 𝑛2-    stuck(L_if)-msec(31)-firings(11)-fps(355)+    𝑛·0·11 := Φ.if( c ↦ 𝜎2:λ )+    𝑛·0·12 := 𝑛·0·11( left ↦ 01-:Δ )+    𝑛·0·13 := 𝑛·0·12( right ↦ 𝑛·0·10 )+    𝔼(L_if):+      𝛿1·7 := 𝔻(𝜎2:λ)  # 𝔻(ξ.c)+      𝑛1·7 := 01-:Δ  # 𝕄(ξ.left)+      𝕄(Φ.a🌵11):+        𝑛·7·1 := Φ.mul( a ↦ 𝜎1:λ:φ )+        𝑛·7·2 := 𝑛·7·1( b ↦ 𝑛·3·1 )+        𝕄(Φ.a🌵11.b):+          𝑛·7·3 := Φ.fact( n ↦ 𝜎3:λ:φ )+        𝔼(L_mul):+          𝛿1·8 := 𝔻(𝜎1:λ)  # 𝔻(ξ.a)+          𝔻(Φ.a🌵13):+            𝕄(Φ.a🌵13):+              𝑛·8·1 := Φ.fact( n ↦ 𝜎3:λ:φ )+              𝑛·8·2 := Φ.if( c ↦ 𝑛·4·1 )+              𝑛·8·3 := 𝑛·8·2( left ↦ 01-:Δ )+              𝑛·8·4 := 𝑛·8·3( right ↦ 𝑛·4·3 )+            𝔼(L_if):+              𝔻(Φ.a🌵14):+                𝕄(Φ.a🌵14):+                  𝑛·9·1 := Φ.zero( x ↦ 𝜎3:λ:φ )+                𝔼(L_zero):+                  𝛿1·10 := 𝔻(𝜎3:λ)  # 𝔻(ξ.x)+                  𝑛·10·1 := 𝜎7:λ  # 𝑛+                  𝑛·10·2 := 𝜎7:λ  # 𝕄(𝑛·10·1)+              𝛿1·9 := 𝔻(𝜎7:λ)  # 𝔻(ξ.c)+              𝑛1·9 := 01-:Δ  # 𝕄(ξ.left)+              𝕄(Φ.a🌵17):+                𝑛·9·2 := Φ.mul( a ↦ 𝜎3:λ:φ )+                𝑛·9·3 := 𝑛·9·2( b ↦ Φ.fact( n ↦ 𝑛·4·4 ) )+                𝕄(Φ.a🌵17.b):+                  𝑛·9·4 := Φ.dec( x ↦ 𝜎3:λ:φ )+                  𝔼(L_dec):+                    𝛿1·11 := 𝔻(𝜎3:λ)  # 𝔻(ξ.x)+                    𝑛·11·1 := 𝜎8:λ:φ  # 𝑛+                    𝑛·11·2 := 𝜎8:λ:φ  # 𝕄(𝑛·11·1)+                  𝑛·9·5 := Φ.fact( n ↦ 𝜎8:λ:φ )+                looped(𝑛·7·2)  # proven+              𝑛2·9 := 𝑛·9·3  # 𝕄(ξ.right)+              𝔻(𝜎9:λ) == 01-+              𝑛3·9 := 𝜎9:λ  # 𝑛1+              𝑛4·9 := 𝑛·9·3  # 𝑛2+              stuck(L_if)+          stuck(L_if)+      𝑛2·7 := 𝑛·7·2  # 𝕄(ξ.right)+      𝔻(𝜎10:λ) == 01-+      𝑛3·7 := 𝜎10:λ  # 𝑛1+      𝑛4·7 := 𝑛·7·2  # 𝑛2+      stuck(L_if) ```  <!-- markdownlint-enable MD013 -->  The first `L_mul` brings its `b` down, and that gets 𝔻 into `fact` with-`n ↦ 𝜎3`, the `formation(…)` line under it. Inside, the fork reduces its right+`n ↦ 𝜎3`, the `𝔻(…):` line under it. Inside, the fork reduces its right branch, and the walk of `--deep` over it would fire `L_mul` with `a ↦ 𝜎3` and `b ↦ Φ.fact( n ↦ 𝜎5 )`: the formation the first `L_mul` was fired with, `𝜎3` standing where `𝜎1` stood and `𝜎5` where `𝜎3` stood, so the firing is cut-before it opens. The cut is the `looped(…)` line under `𝑛.6.2`, standing where-the block of the cut firing would have stood and commented with the judgment-the frame belonged to, the site it was cut at and the mode that cut it. What it-carries is the formation the frame above entered, as that frame had it, so the-two are paired by their terms and no reader has to rename symbols by eye or-find the cut in the residue. Nothing runs under a cut, so no block opens under-the line. In the XML protocol it is-`<looped by="morph" match="proven" at="Φ.a🌵7"><e>…</e></looped>`, with the-site and the mode as attributes and the formation in `<e>`. Without the option+before it opens. The cut is the `looped(…)` line in the block `𝕄(Φ.a🌵7):`,+standing where the block of the cut firing would have stood: the block names+the judgment the frame belonged to and the site it was cut at, and the comment+names the mode that cut it. What it+carries is the formation the frame above entered, named by the line that made+it, `𝑛·0·10`, so the two are paired by their terms and no reader has to rename+symbols by eye or find the cut in the residue. Nothing runs under a cut, so no+block opens under the line. In the XML protocol it is+`<looped by="morph" match="proven" at="Φ.a🌵7"><e>𝑛·0·10</e></looped>`, with+the site and the mode as attributes and the formation in `<e>`. Without the option the same run nests one round inside another until `--max-steps` runs out.  A cut at the `φ` of a copy the walk of `--deep` has placed, such as `Φ.a🌵4.φ`, answers that copy with a fresh symbol, the way a deferred copy is answered. A fork above it then joins that symbol with its other branch, instead of getting stuck on a copy nobody can read. The line names the-symbol, as in `looped(…) := 𝜎6  # 𝕄(Φ.a🌵4.φ), plausible`, and the markup+symbol, as in `looped(…) := 𝜎6  # plausible` in the block `𝕄(Φ.a🌵4.φ):`,+and the markup writes the object the copy was made of and its arguments the way it writes them for a deferred copy, on one line, broken here for reading: @@ -1495,7 +1687,7 @@ ```xml <looped symbol="𝜎6" by="morph" match="plausible" at="Φ.a🌵4.φ" of="Φ.fact">   <with><attr name="n">𝜎3</attr><attr name="acc">?</attr></with>-  <e>⟦ c ↦ 𝜎2:λ, left ↦ 00-:Δ, right ↦ Φ.fact( n ↦ 𝜎3:λ:φ, acc ↦ Φ.pair( head ↦ 𝜎1:λ:φ, tail ↦ 00-:Δ ) ), λ ⤍ L_if ⟧</e>+  <e>𝑛·0·16</e> </looped> ``` @@ -1528,13 +1720,13 @@   dec ↦ ⟦ x ↦ ∅, λ ⤍ L_dec ⟧,   pair ↦ ⟦ head ↦ ∅, tail ↦ ∅ ⟧,   fact ↦ ⟦ n ↦ ∅, acc ↦ ∅, φ ↦ Φ.if( c ↦ Φ.zero( x ↦ ξ.n ), left ↦ ξ.acc, right ↦ Φ.fact( n ↦ Φ.dec( x ↦ ξ.n ), acc ↦ Φ.pair( head ↦ ξ.n, tail ↦ ξ.acc ) ) ) ⟧,-  x ↦ Φ.fact( n ↦ ⟦ λ ⤍ 𝜎1 ⟧, acc ↦ ⟦ Δ ⤍ 00- ⟧ )+  x ↦ Φ.fact( n ↦ ⟦ φ ↦ ⟦ λ ⤍ 𝜎1 ⟧ ⟧, acc ↦ ⟦ Δ ⤍ 00- ⟧ ) ⟧ $ phino morph --deep --acyclic=plausible --partial --sweet --hide-rho --flat \     --symbolic=facta.yaml --locator='Q.x' --protocol=facta.txt facta.phi-⟦ n ↦ 𝜎1:λ, acc ↦ 00-:Δ, φ ↦ Φ.if( c ↦ 𝜎2:λ, left ↦ acc, right ↦ Φ.fact( n ↦ 𝜎3:λ, acc ↦ Φ.pair( head ↦ n, tail ↦ acc ) ) ) ⟧+⟦ n ↦ 𝜎1:λ:φ, acc ↦ 00-:Δ, φ ↦ 𝜎8:λ ⟧ $ grep looped facta.txt-looped(⟦ c ↦ 𝜎2:λ, left ↦ 00-:Δ, right ↦ Φ.fact( n ↦ 𝜎3:λ, acc ↦ Φ.pair( head ↦ 𝜎1:λ, tail ↦ 00-:Δ ) ), λ ⤍ L_if ⟧)  # 𝕄(Φ.a🌵4.φ), plausible+          looped(𝑛·0·16) := 𝜎6  # plausible ```  <!-- markdownlint-enable MD013 -->@@ -1685,21 +1877,49 @@     --protocol=sums.txt --sweet --hide-rho sums.phi ⟦ a ↦ ⟦ φ ↦ 𝜎1:λ, plus(x) ↦ L_plus:λ ⟧, b ↦ ⟦ φ ↦ 𝜎2:λ, plus(x) ↦ L_plus:λ ⟧ ⟧ $ cat sums.txt-𝕄(Φ.l🌵)-  𝔼(L_plus)  # 𝕄(Φ.l🌵.a)-    formation(⟦ φ ↦ 01-:Δ, plus(x) ↦ L_plus:λ ⟧)  # 𝔻(Φ.a🌵1-0)-    𝛿1.1 := 01-  # 𝔻(ξ.ρ)-    formation(⟦ φ ↦ 02-:Δ, plus(x) ↦ L_plus:λ ⟧)  # 𝔻(Φ.a🌵1-1)-    𝛿2.1 := 02-  # 𝔻(ξ.x)-    𝑛.1.1 := Φ.num( φ ↦ 𝜎1:λ )  # 𝑛-    𝑛.1.2 := ⟦ φ ↦ 𝜎1:λ, plus(x) ↦ L_plus:λ ⟧  # 𝕄(𝑛.1.1)-  𝔼(L_plus)  # 𝕄(Φ.l🌵.b)-    formation(⟦ φ ↦ 03-:Δ, plus(x) ↦ L_plus:λ ⟧)  # 𝔻(Φ.a🌵2-0)-    𝛿1.2 := 03-  # 𝔻(ξ.ρ)-    formation(⟦ φ ↦ 04-:Δ, plus(x) ↦ L_plus:λ ⟧)  # 𝔻(Φ.a🌵2-1)-    𝛿2.2 := 04-  # 𝔻(ξ.x)-    𝑛.2.1 := Φ.num( φ ↦ 𝜎2:λ )  # 𝑛-    𝑛.2.2 := ⟦ φ ↦ 𝜎2:λ, plus(x) ↦ L_plus:λ ⟧  # 𝕄(𝑛.2.1)+𝕄(Φ.l🌵):+  𝕄(Φ.l🌵.a):+    𝑛·0·1 := Φ.num( φ ↦ 01-:Δ )+    𝑛·0·2 := Φ.num( φ ↦ 01-:Δ )+    𝑛·0·3 := Φ.num( φ ↦ 02-:Δ )+    𝑛·0·4 := Φ.num( φ ↦ 01-:Δ )+    𝑛·0·5 := 𝑛·0·4.plus( x ↦ 𝑛·0·3 )+    𝔼(L_plus):+      𝔻(Φ.a🌵1-0):+        𝕄(Φ.a🌵1-0):+          𝑛·1·1 := Φ.num( φ ↦ 01-:Δ )+        𝛿·1·1 := 01-+      𝛿1·1 := 𝛿·1·1  # 𝔻(ξ.ρ)+      𝔻(Φ.a🌵1-1):+        𝕄(Φ.a🌵1-1):+          𝑛·1·2 := Φ.num( φ ↦ 02-:Δ )+        𝛿·1·2 := 02-+      𝛿2·1 := 𝛿·1·2  # 𝔻(ξ.x)+      𝑛·1·3 := Φ.num( φ ↦ 𝜎1:λ )  # 𝑛+      𝕄(𝑛·1·3):+        𝑛·1·4 := Φ.num( φ ↦ 𝜎1:λ )+      𝑛·1·5 := 𝑛·1·4  # 𝕄(𝑛·1·3)+  𝕄(Φ.l🌵.b):+    𝑛·0·6 := Φ.num( φ ↦ 03-:Δ )+    𝑛·0·7 := Φ.num( φ ↦ 03-:Δ )+    𝑛·0·8 := Φ.num( φ ↦ 04-:Δ )+    𝑛·0·9 := Φ.num( φ ↦ 03-:Δ )+    𝑛·0·10 := 𝑛·0·9.plus( x ↦ 𝑛·0·8 )+    𝔼(L_plus):+      𝔻(Φ.a🌵2-0):+        𝕄(Φ.a🌵2-0):+          𝑛·2·1 := Φ.num( φ ↦ 03-:Δ )+        𝛿·2·1 := 03-+      𝛿1·2 := 𝛿·2·1  # 𝔻(ξ.ρ)+      𝔻(Φ.a🌵2-1):+        𝕄(Φ.a🌵2-1):+          𝑛·2·2 := Φ.num( φ ↦ 04-:Δ )+        𝛿·2·2 := 04-+      𝛿2·2 := 𝛿·2·2  # 𝔻(ξ.x)+      𝑛·2·3 := Φ.num( φ ↦ 𝜎2:λ )  # 𝑛+      𝕄(𝑛·2·3):+        𝑛·2·4 := Φ.num( φ ↦ 𝜎2:λ )+      𝑛·2·5 := 𝑛·2·4  # 𝕄(𝑛·2·3) ```  A fresh name a binding mints carries its place in the formation, `a🌵2-0` for@@ -2343,6 +2563,7 @@ [latex]: https://en.wikipedia.org/wiki/LaTeX [java]: https://www.java.com/en/download/ [curl]: https://curl.se/+[gha]: https://docs.github.com/en/actions [jna]: https://github.com/java-native-access/jna [jna-native]: https://github.com/java-native-access/jna/blob/master/src/com/sun/jna/Native.java [jeo]: https://github.com/objectionary/jeo-maven-plugin
benchmark/Main.hs view
@@ -15,7 +15,7 @@ import Data.String (fromString) import Data.Time.Clock import Dataize (reduction)-import Deps (Acyclic (Plausible, Proven), Judgment (Morphing), dontSaveEval, dontSaveStep)+import Deps (Acyclic (Plausible, Proven), Judgment (Morphing), dontSaveEval, dontSaveMade, dontSaveStep) import Encoding (Encoding (UNICODE)) import Engine (Engine (_matching, _normal), building, stepOf, yaml) import Evaluate (evaluation, fired)@@ -60,6 +60,7 @@     MtDisabled     Nothing     dontSaveStep+    dontSaveMade  symbolicCtx :: Acyclic -> Maybe Memo -> IORef Int -> Lambdas -> Expression -> ReduceContext symbolicCtx acyclic memo minted lambdas locator =@@ -75,6 +76,7 @@     Nothing     memo     1+    Nothing     False     False     True
phino.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: phino-version: 0.0.150+version: 0.0.151 license: MIT synopsis: Command-Line Manipulator of 𝜑-Calculus Expressions description: Please see the README on GitHub at <https://github.com/objectionary/phino#readme>
src/CLI/Runners.hs view
@@ -183,7 +183,7 @@       _protocol       printCtx       ( \record -> do-          let ctx = ReduceContext loc loc Nothing _maxDepth _maxCycles (Steps _maxSteps 0) tally minted deadline memo 1 _depthSensitive _shuffle _partial False 1 _acyclic Dataization [] Map.empty lambdas (building linked) reduction evaluation fired save record linked+          let ctx = ReduceContext loc loc Nothing _maxDepth _maxCycles (Steps _maxSteps 0) tally minted deadline memo 1 (Just (1, Dataization, loc)) _depthSensitive _shuffle _partial False 1 _acyclic Dataization [] Map.empty lambdas (building linked) reduction evaluation fired save record linked           (universe, aiming) <- aimed printCtx Dataization _inside expr ctx           started universe aiming           dataize universe emptyState aiming@@ -265,7 +265,7 @@       _protocol       printCtx       ( \record -> do-          let ctx = ReduceContext loc loc Nothing _maxDepth _maxCycles (Steps _maxSteps 0) tally minted deadline memo 1 _depthSensitive _shuffle _partial _deep _jobs _acyclic Morphing [] Map.empty lambdas (building linked) reduction evaluation fired save record linked+          let ctx = ReduceContext loc loc Nothing _maxDepth _maxCycles (Steps _maxSteps 0) tally minted deadline memo 1 (Just (1, Morphing, loc)) _depthSensitive _shuffle _partial _deep _jobs _acyclic Morphing [] Map.empty lambdas (building linked) reduction evaluation fired save record linked           (universe, aiming) <- aimed printCtx Morphing _inside expr ctx           started universe aiming           morph universe emptyState aiming
src/CLI/Validators.hs view
@@ -6,7 +6,8 @@ import AST import CLI.Types import Control.Exception-import Control.Monad (forM_, when, (>=>))+import Control.Monad (forM_, unless, when, (>=>))+import Data.Char (isAlphaNum) import Data.Foldable (for_) import Data.List (isPrefixOf) import Data.Maybe (isJust)@@ -63,7 +64,14 @@     inside _ _ = False  validateLatexOptions :: IOFormat -> [(Bool, String)] -> [(Maybe String, String)] -> [(Maybe Int, String)] -> IO ()-validateLatexOptions LATEX _ _ _ = pure ()+validateLatexOptions LATEX _ strings _ = forM_ strings validateLatexString+  where+    validateLatexString (Just label, "label") =+      unless (all safeLabelCharacter label) $+        invalidCLIArguments+          "The --label option must contain only letters, numbers, colons, periods, underscores, and hyphens"+    validateLatexString _ = pure ()+    safeLabelCharacter character = isAlphaNum character || character `elem` ":._-" validateLatexOptions _ bools strings ints = do   let (bools', opts) = unzip bools       msg = "The --%s option can stay together with --output=latex only"
src/Dataize.hs view
@@ -11,7 +11,7 @@  import AST import Control.Exception (throwIO, try)-import Control.Monad (unless)+import Control.Monad (unless, when) import Data.List.NonEmpty (NonEmpty (..)) import qualified Data.List.NonEmpty as NE import Data.Maybe (listToMaybe)@@ -20,7 +20,7 @@ import Engine (Engine (..)) import qualified Inference as In import Locator (locatedExpression)-import Morph (Morphed, ReduceContext (..), ReduceException (..), ReductionFunc, boxed, deeper, entering, inferred, insideUniverse, leadsTo, onward, parking, universed)+import Morph (Morphed, ReduceContext (..), ReduceException (..), ReductionFunc, deeper, entering, inferred, insideUniverse, leadsTo, onward, opening, parking, universed) import Rewriter (Rewritten)  type Dataized = (Bytes, [Rewritten])@@ -50,14 +50,14 @@  dataize' :: Dataizable -> Expression -> State -> ReduceContext -> IO (Dataized, State) dataize' (expr, seq) univ state caller = do-  guarded <- deeper =<< entering expr =<< universed univ caller{_judgment = Dataization}-  ctx <- inside guarded expr+  ctx <- opening Dataization =<< deeper =<< entering expr =<< universed univ caller{_judgment = Dataization}   parking seq state $ case unknown expr of     Just idx -> manufactured idx ctx     Nothing -> do       reached <- inferred expr univ state ctx ctx._engine._dataization       case reached of         Just (In.Answered step bts, state') -> do+          when (step == (Dataization, "delta")) (ctx._saveEval (EvDelta ctx._nesting bts))           seq' <- leadsTo seq step (ExBytes bts) ctx           pure ((bts, NE.toList seq'), state'{_manufactured = Nothing})         Just (In.Onward way built world, state') -> do@@ -65,12 +65,6 @@           dataize' dataizable world state'' ctx         Nothing -> throwIO (Undataizable expr state)   where-    inside :: ReduceContext -> Expression -> IO ReduceContext-    inside ctx (ExFormation bds)-      | boxed bds = do-          ctx._saveEval (EvFormation ctx._nesting expr ctx._site)-          pure ctx{_nesting = ctx._nesting + 1}-    inside ctx _ = pure ctx     unknown :: Expression -> Maybe Int     unknown (ExFormation bds) = listToMaybe [idx | BiLambda (FnSymbol idx) <- bds]     unknown _ = Nothing
src/Deps.hs view
@@ -9,8 +9,9 @@ module Deps where  import AST+import Bytes (btsSize, btsToNum) import Control.Monad (unless, when)-import Data.Bifunctor (bimap)+import Data.Bifunctor (bimap, first) import Data.IORef (IORef, readIORef, writeIORef) import Data.List (intercalate) import qualified Data.Map.Strict as Map@@ -98,7 +99,8 @@ data Evaluation   = EvRun Judgment T.Text   | EvFiring Int T.Text Judgment Expression-  | EvFormation Int Expression Expression+  | EvStarted Int Judgment Expression+  | EvDelta Int Bytes   | EvLooped Int Judgment Acyclic Expression Expression (Maybe (Int, Maybe Expression))   | EvStuck Int T.Text Judgment Expression   | EvStall Int T.Text@@ -127,7 +129,7 @@   where     record :: Evaluation -> Evaluation     record (EvFiring depth key judgment site) = EvFiring depth key judgment (term site)-    record (EvFormation depth self site) = EvFormation depth (term self) (term site)+    record (EvStarted depth judgment site) = EvStarted depth judgment (term site)     record (EvLooped depth judgment mode self site answered) = EvLooped depth judgment mode (term self) (term site) (fmap (bimap symbol (fmap term)) answered)     record (EvStuck depth key judgment self) = EvStuck depth key judgment (term self)     record (EvStarved depth limit judgment site) = EvStarved depth limit judgment (term site)@@ -156,10 +158,34 @@     datum :: Either Int Bytes -> Either Int Bytes     datum = either (Left . symbol) Right +resited :: Expression -> Expression -> Evaluation -> Evaluation+resited from to = record+  where+    record :: Evaluation -> Evaluation+    record (EvFiring depth key judgment site) = EvFiring depth key judgment (moved site)+    record (EvStarted depth judgment site) = EvStarted depth judgment (moved site)+    record (EvLooped depth judgment mode self site answered) = EvLooped depth judgment mode self (moved site) answered+    record (EvStarved depth limit judgment site) = EvStarved depth limit judgment (moved site)+    record (EvTimeout depth limit judgment site) = EvTimeout depth limit judgment (moved site)+    record (EvSpent depth limit judgment site) = EvSpent depth limit judgment (moved site)+    record (EvDeferred depth sym judgment copy call site) = EvDeferred depth sym judgment copy call (moved site)+    record (EvApplied depth judgment call object site) = EvApplied depth judgment call object (moved site)+    record other = other+    moved :: Expression -> Expression+    moved site+      | site == from = to+      | otherwise = site++ieee :: Bytes -> Maybe String+ieee bytes+  | btsSize bytes == 8 = Just (show (either fromIntegral id (btsToNum bytes) :: Double))+  | otherwise = Nothing+ tier :: Evaluation -> Int tier EvRun{} = 0 tier (EvFiring depth _ _ _) = depth-tier (EvFormation depth _ _) = depth+tier (EvStarted depth _ _) = depth+tier (EvDelta depth _) = depth tier (EvLooped depth _ _ _ _ _) = depth tier (EvStuck depth _ _ _) = depth tier (EvStall depth _) = depth@@ -219,10 +245,14 @@   , _made :: Named Expression   , _counted :: Map.Map Int Int   , _built :: Map.Map Int Int+  , _deltas :: Map.Map Int Int+  , _found :: Maybe (Bytes, String)+  , _blocks :: [(Int, Maybe String, Bool)]+  , _answered :: [(Int, Expression, String)]   }  emptyProtocol :: Protocol-emptyProtocol = Protocol 0 Map.empty [] False Map.empty Map.empty Map.empty+emptyProtocol = Protocol 0 Map.empty [] False Map.empty Map.empty Map.empty Map.empty Nothing [] []  data Nesting = Nesting   { _fires :: Int@@ -230,20 +260,55 @@   , _closing :: [(Int, String)]   , _objects :: Named Expression   , _numbered :: Map.Map Int Int+  , _datums :: Map.Map Int Int+  , _held :: Maybe (Bytes, String)+  , _heads :: [(Int, String)]+  , _pending :: [(Int, String, String)]+  , _sources :: [(Int, Expression, String)]   }  emptyNesting :: Nesting-emptyNesting = Nesting 0 [] [] Map.empty Map.empty+emptyNesting = Nesting 0 [] [] Map.empty Map.empty Map.empty Nothing [] [] []  saveEval :: Handle -> IORef Protocol -> (Expression -> IO String) -> (Expression -> IO String) -> SaveEvalFunc saveEval handle cursor printed printed' report = do-  line <- atomicModify cursor (written report . outer (tier report))-  mapM_ saved line+  made <- atomicModify cursor (fmap (first (forgotten report) . headed) . written report . beside report . outer (tier report))+  mapM_ saved made   where+    forgotten :: Evaluation -> Protocol -> Protocol+    forgotten EvDelta{} protocol = protocol+    forgotten _ protocol = protocol{_found = Nothing}+    beside :: Evaluation -> Protocol -> Protocol+    beside EvStarted{} protocol = protocol+    beside EvComputed{} protocol = protocol+    beside EvMinted{} protocol = protocol+    beside report' protocol = protocol{_blocks = dropWhile (\(level, _, _) -> level >= tier report') protocol._blocks}+    headed :: (Protocol, Maybe String) -> (Protocol, [String])+    headed (protocol, Nothing) = (protocol, [])+    headed (protocol, Just line) =+      ( protocol{_blocks = [(level, heading, True) | (level, heading, _) <- protocol._blocks]}+      , [indented level (heading ++ ":") | (level, Just heading, False) <- reverse protocol._blocks] ++ [line]+      )     render :: Expression -> IO String     render term = do       protocol <- readIORef cursor       printed (abbreviated protocol._made term)+    located :: Protocol -> Expression -> IO String+    located protocol site = case [naming | (_, built, naming) <- protocol._answered, built == site] of+      naming : _ -> pure naming+      [] -> render site+    context :: Protocol -> Judgment -> Expression -> IO [String]+    context protocol judgment site = do+      locator <- located protocol site+      let said = printf "%s(%s)" (letter judgment) locator+      pure [said | innermost protocol /= Just said]+    innermost :: Protocol -> Maybe String+    innermost protocol = case protocol._blocks of+      (_, heading, _) : _ -> heading+      [] -> Nothing+    remarked :: String -> [String] -> String+    remarked line [] = line+    remarked line remarks = printf "%s  # %s" line (intercalate ", " remarks)     salted :: Expression -> IO String     salted term = do       protocol <- readIORef cursor@@ -254,27 +319,40 @@       logDebug (printf "Saved one line of the protocol: %s" (dropWhile (== ' ') line))     written :: Evaluation -> Protocol -> IO (Protocol, Maybe String)     written (EvRun judgment locator) protocol =-      pure (protocol{_begun = True}, Just (printf "%s(%s)" (letter judgment) (T.unpack locator)))+      pure (protocol{_begun = True, _blocks = [(0, Just heading, True)]}, Just (heading ++ ":"))+      where+        heading :: String+        heading = printf "%s(%s)" (letter judgment) (T.unpack locator)     written (EvFiring depth key judgment site) protocol = do-      locator <- render site+      remarks <- context protocol judgment site       pure         ( protocol             { _fired = firings             , _open = (depth, firings) : protocol._open+            , _blocks = (depth, Nothing, True) : protocol._blocks             }-        , Just (indented depth (printf "𝔼(%s)  # %s(%s)" (T.unpack key) (letter judgment) locator))+        , Just (indented depth (remarked (printf "𝔼(%s):" (T.unpack key)) remarks))         )       where         firings :: Int         firings = protocol._fired + 1-    written (EvFormation depth self site) protocol = do-      form <- render self-      locator <- render site-      pure (protocol, Just (indented depth (printf "formation(%s)  # %s(%s)" form (letter Dataization) locator)))+    written (EvStarted depth judgment site) protocol = do+      locator <- located protocol site+      let heading = printf "%s(%s)" (letter judgment) locator+          inner = dropWhile (\(level, _, _) -> level > depth) protocol._blocks+      pure $ case inner of+        (level, Just heading', _) : _ | level == depth && heading' == heading -> (protocol{_blocks = inner}, Nothing)+        _ -> (protocol{_blocks = (depth, Just heading, False) : dropWhile (\(level, _, _) -> level >= depth) inner}, Nothing)+    written (EvDelta depth bytes) protocol = do+      datum <- render (ExBytes bytes)+      let index = maybe 1 (+ 1) (Map.lookup (opener protocol) protocol._deltas)+          naming :: String+          naming = printf "%s·%d" (labelled protocol sigil) index+      pure (protocol{_deltas = Map.insert (opener protocol) index protocol._deltas, _found = Just (bytes, naming)}, Just (indented depth (remarked (printf "%s := %s" naming datum) (maybe [] pure (ieee bytes)))))     written (EvLooped depth judgment mode self site answered) protocol = do       form <- render self-      locator <- render site-      pure (protocol, Just (indented depth (printf "looped(%s)%s  # %s(%s), %s" form (maybe "" symbolized answered) (letter judgment) locator (certainty mode))))+      remarks <- context protocol judgment site+      pure (protocol, Just (indented depth (remarked (printf "looped(%s)%s" form (maybe "" symbolized answered)) (remarks ++ [certainty mode]))))       where         symbolized :: (Int, Maybe Expression) -> String         symbolized (symbol, _) = printf " := %s" (printFunction (FnSymbol symbol))@@ -286,16 +364,16 @@     written (EvStuckOn depth key) protocol =       pure (protocol, Just (indented depth (printf "stuck(%s)" (T.unpack key))))     written (EvStarved depth limit judgment site) protocol = do-      locator <- render site-      pure (protocol, Just (indented depth (printf "starved(%d)  # %s(%s)" limit (letter judgment) locator)))+      remarks <- context protocol judgment site+      pure (protocol, Just (indented depth (remarked (printf "starved(%d)" limit) remarks)))     written (EvTimeout depth limit judgment site) protocol = do-      locator <- render site-      pure (protocol, Just (indented depth (printf "timeout(%d)  # %s(%s)" limit (letter judgment) locator)))+      remarks <- context protocol judgment site+      pure (protocol, Just (indented depth (remarked (printf "timeout(%d)" limit) remarks)))     written (EvSpent depth limit judgment site) protocol = do-      locator <- render site-      pure (protocol, Just (indented depth (printf "spent(%d)  # %s(%s)" limit (letter judgment) locator)))+      remarks <- context protocol judgment site+      pure (protocol, Just (indented depth (remarked (printf "spent(%d)" limit) remarks)))     written (EvData depth spelling operand value) protocol = do-      datum <- spelled value+      datum <- maybe (spelled value) pure (found value protocol._found)       line <- commented (printf "%s := %s" (labelled protocol spelling) datum) Dataization operand       pure (protocol, Just (indented depth line))       where@@ -335,28 +413,29 @@     written EvMinted{} protocol = pure (protocol, Nothing)     written (EvDeferred depth symbol judgment copy call site) protocol = do       form <- maybe (render copy) (printed . abbreviatedInside protocol._made) call-      locator <- render site-      pure (protocol, Just (indented depth (printf "deferred(%s) := %s  # %s(%s)" (printFunction (FnSymbol symbol)) form (letter judgment) locator)))+      remarks <- context protocol judgment site+      pure (protocol, Just (indented depth (remarked (printf "deferred(%s) := %s" (printFunction (FnSymbol symbol)) form) remarks)))     written (EvApplied depth judgment call object site) protocol = do       let (index, counted) = numbered protocol           aliased :: Expression           aliased = alias (opener protocol) index       form <- printed (abbreviatedInside protocol._made call)-      locator <- render site-      pure (counted{_made = namedInsert call aliased (namedInsert object aliased counted._made)}, Just (indented depth (printf "applied(%s.%d) := %s  # %s(%s)" (labelled protocol answer) index form (letter judgment) locator)))+      remarks <- context protocol judgment site+      pure (counted{_made = namedInsert call aliased (namedInsert object aliased counted._made)}, Just (indented depth (remarked (printf "%s·%d := %s" (labelled protocol answer) index form) remarks)))     written (EvComputed _ before after) protocol = pure (protocol{_made = namedCarry before after protocol._made}, Nothing)     written (EvBuilt depth term) protocol = do       let (index, counted) = numbered protocol       value <- borrowed protocol term-      pure (counted{_built = Map.insert (opener protocol) index counted._built}, Just (indented depth (printf "%s.%d := %s  # %s" (labelled protocol answer) index value (T.unpack answer))))+      let naming = printf "%s·%d" (labelled protocol answer) index+      pure (counted{_built = Map.insert (opener protocol) index counted._built, _answered = (depth, term, naming) : counted._answered}, Just (indented depth (printf "%s := %s  # %s" naming value (T.unpack answer))))     written (EvAnswer depth term) protocol = do       let (index, counted) = numbered protocol           stem :: String           stem = labelled protocol answer           naming :: String-          naming = printf "%s.%d" stem index+          naming = printf "%s·%d" stem index       (protocol', value) <- valued counted naming term-      pure (protocol', Just (indented depth (printf "%s := %s  # 𝕄(%s.%d)" naming value stem (Map.findWithDefault 1 (opener protocol) protocol._built))))+      pure (protocol', Just (indented depth (printf "%s := %s  # 𝕄(%s·%d)" naming value stem (Map.findWithDefault 1 (opener protocol) protocol._built))))     valued :: Protocol -> String -> Expression -> IO (Protocol, String)     valued protocol naming term = case denoted term of       Nothing -> (,) protocol <$> render term@@ -372,9 +451,9 @@     commented' :: String -> Expression -> IO String     commented' line source = printf "%s  # %s" line <$> salted source     outer :: Int -> Protocol -> Protocol-    outer depth protocol = protocol{_open = dropWhile ((>= depth) . fst) protocol._open}+    outer depth protocol = protocol{_open = dropWhile ((>= depth) . fst) protocol._open, _answered = dropWhile (\(level, _, _) -> level > depth) protocol._answered}     labelled :: Protocol -> T.Text -> String-    labelled protocol spelling = printf "%s.%d" (T.unpack spelling) (opener protocol)+    labelled protocol spelling = printf "%s·%d" (T.unpack spelling) (opener protocol)     opener :: Protocol -> Int     opener protocol = maybe 0 snd (listToMaybe protocol._open)     numbered :: Protocol -> (Int, Protocol)@@ -401,7 +480,7 @@  saveEvalXml :: Handle -> IORef Nesting -> (Expression -> IO String) -> SaveEvalFunc saveEvalXml handle cursor printed report = do-  written <- atomicModify cursor (elements report . outer (tier report))+  written <- atomicModify cursor (opened' . flushed . beside report . outer (tier report))   mapM_ (hPutStrLn handle) written   logDebug (printf "Saved %d line(s) of the XML protocol" (length written))   where@@ -409,6 +488,27 @@     render term = do       nesting <- readIORef cursor       printed (abbreviated nesting._objects term)+    located :: Nesting -> Expression -> IO String+    located nesting site = case [naming | (_, built, naming) <- nesting._sources, built == site] of+      naming : _ -> pure naming+      [] -> render site+    opened' :: (Nesting, [String]) -> IO (Nesting, [String])+    opened' (nesting, openings) = bimap (forgotten report) (openings ++) <$> elements report nesting+    beside :: Evaluation -> Nesting -> Nesting+    beside EvStarted{} nesting = nesting+    beside EvComputed{} nesting = nesting+    beside report' nesting = nesting{_heads = dropWhile ((>= tier report') . fst) nesting._heads, _pending = dropWhile (\(level, _, _) -> level >= tier report') nesting._pending}+    flushed :: Nesting -> (Nesting, [String])+    flushed nesting+      | silent report = (nesting, [])+      | otherwise = (nesting{_pending = [], _closing = [(level, element) | (level, element, _) <- nesting._pending] ++ nesting._closing}, [opening | (_, _, opening) <- reverse nesting._pending])+    silent :: Evaluation -> Bool+    silent EvStarted{} = True+    silent EvComputed{} = True+    silent _ = False+    forgotten :: Evaluation -> Nesting -> Nesting+    forgotten EvDelta{} nesting = nesting+    forgotten _ nesting = nesting{_held = Nothing}     elements :: Evaluation -> Nesting -> IO (Nesting, [String])     elements (EvRun judgment locator) nesting =       pure@@ -420,7 +520,7 @@           ]         )     elements (EvFiring depth key judgment site) nesting = do-      locator <- render site+      locator <- located nesting site       pure         ( nesting             { _fires = fires@@ -433,14 +533,18 @@         (kept, closers) = closed depth nesting._closing         fires :: Int         fires = nesting._fires + 1-    elements (EvFormation depth self site) nesting = do-      form <- render self-      locator <- render site-      let (kept, closers) = closed depth nesting._closing-      pure (nesting{_closing = (depth, "formation") : kept}, closers ++ [indentedXml depth (printf "<formation at=\"%s\" term=\"%s\">" (escapeXML locator) (escapeXML form))])+    elements (EvStarted depth judgment site) nesting = do+      locator <- located nesting site+      let opening = indentedXml depth (printf "<%s at=\"%s\">" (opened judgment) (escapeXML locator))+          inner = dropWhile ((> depth) . fst) nesting._heads+          pending = dropWhile (\(level, _, _) -> level > depth) nesting._pending+          (kept, closers) = closed depth nesting._closing+      pure $ case inner of+        (level, opening') : _ | level == depth && opening' == opening -> (nesting{_heads = inner, _pending = pending}, [])+        _ -> (nesting{_heads = (depth, opening) : dropWhile ((>= depth) . fst) inner, _pending = (depth, opened judgment, opening) : dropWhile (\(level, _, _) -> level >= depth) pending, _closing = kept}, closers)     elements (EvLooped depth judgment mode self site answered) nesting = do       form <- render self-      locator <- render site+      locator <- located nesting site       (origin, given) <- maybe (pure ("", "")) called (answered >>= snd)       let (kept, closers) = closed depth nesting._closing       pure (nesting{_closing = kept}, closers ++ [indentedXml depth (printf "<looped%s by=\"%s\" match=\"%s\" at=\"%s\"%s>%s<e>%s</e></looped>" (maybe "" symbolized answered) (opened judgment) (certainty mode) (escapeXML locator) origin given (escapeXMLText form))])@@ -458,19 +562,26 @@       let (kept, closers) = closed depth nesting._closing       pure (nesting{_closing = kept}, closers ++ [indentedXml depth (printf "<unfinished λ=\"%s\"/>" (quoted key))])     elements (EvStarved depth limit judgment site) nesting = do-      locator <- render site+      locator <- located nesting site       let (kept, closers) = closed depth nesting._closing       pure (nesting{_closing = kept}, closers ++ [indentedXml depth (printf "<starved limit=\"%d\" by=\"%s\" at=\"%s\"/>" limit (opened judgment) (escapeXML locator))])     elements (EvTimeout depth limit judgment site) nesting = do-      locator <- render site+      locator <- located nesting site       let (kept, closers) = closed depth nesting._closing       pure (nesting{_closing = kept}, closers ++ [indentedXml depth (printf "<timeout limit=\"%d\" by=\"%s\" at=\"%s\"/>" limit (opened judgment) (escapeXML locator))])     elements (EvSpent depth limit judgment site) nesting = do-      locator <- render site+      locator <- located nesting site       let (kept, closers) = closed depth nesting._closing       pure (nesting{_closing = kept}, closers ++ [indentedXml depth (printf "<spent limit=\"%d\" by=\"%s\" at=\"%s\"/>" limit (opened judgment) (escapeXML locator))])+    elements (EvDelta depth bytes) nesting = do+      datum <- render (ExBytes bytes)+      let index = maybe 1 (+ 1) (Map.lookup (opener nesting) nesting._datums)+          naming :: String+          naming = printf "%s·%d" (labelled nesting sigil) index+          (kept, closers) = closed depth nesting._closing+      pure (nesting{_closing = kept, _datums = Map.insert (opener nesting) index nesting._datums, _held = Just (bytes, naming)}, closers ++ [indentedXml depth (printf "<delta meta=\"%s\"%s>%s</delta>" (escapeXML naming) (maybe "" (printf " number=\"%s\"" . escapeXML) (ieee bytes) :: String) (escapeXMLText datum))])     elements (EvData depth spelling _ value) nesting = do-      record <- stood value+      record <- maybe (stood value) (pure . printf "<bind meta=\"%s\">%s</bind>" (escapeXML (labelled nesting spelling)) . escapeXMLText) (found value nesting._held)       pure (nesting{_closing = kept}, closers ++ [indentedXml depth record])       where         (kept, closers) = closed depth nesting._closing@@ -524,17 +635,17 @@         spelled (Right bytes) = render (ExBytes bytes)     elements (EvDeferred depth symbol judgment copy call site) nesting = do       form <- render copy-      locator <- render site+      locator <- located nesting site       (origin, given) <- maybe (pure ("", "")) called call       let (kept, closers) = closed depth nesting._closing       pure (nesting{_closing = kept}, closers ++ [indentedXml depth (printf "<deferred symbol=\"%s\" by=\"%s\" at=\"%s\"%s>%s<e>%s</e></deferred>" (sigma symbol) (opened judgment) (escapeXML locator) origin given (escapeXMLText form))])     elements (EvApplied depth judgment call object site) nesting = do       (origin, given) <- parted (abbreviatedInside nesting._objects call)-      locator <- render site+      locator <- located nesting site       let (index, counted) = numbered nesting           (kept, closers) = closed depth nesting._closing           naming :: String-          naming = printf "%s.%d" (labelled nesting answer) index+          naming = printf "%s·%d" (labelled nesting answer) index           aliased :: Expression           aliased = alias (opener nesting) index       pure (counted{_closing = kept, _objects = namedInsert call aliased (namedInsert object aliased counted._objects)}, closers ++ [indentedXml depth (printf "<applied meta=\"%s\" by=\"%s\" at=\"%s\" of=\"%s\">%s</applied>" (escapeXML naming) (opened judgment) (escapeXML locator) (escapeXML origin) given)])@@ -544,19 +655,19 @@       let (index, counted) = numbered nesting           (kept, closers) = closed depth nesting._closing           naming :: String-          naming = printf "%s.%d" (labelled nesting answer) index-      pure (counted{_closing = kept}, closers ++ [indentedXml depth (printf "<built meta=\"%s\">%s</built>" (escapeXML naming) (escapeXMLText body))])+          naming = printf "%s·%d" (labelled nesting answer) index+      pure (counted{_closing = kept, _sources = (depth, term, naming) : counted._sources}, closers ++ [indentedXml depth (printf "<built meta=\"%s\">%s</built>" (escapeXML naming) (escapeXMLText body))])     elements (EvAnswer depth term) nesting = do       body <- render term       let (index, counted) = numbered nesting           (kept, closers) = closed depth nesting._closing           naming :: String-          naming = printf "%s.%d" (labelled nesting answer) index+          naming = printf "%s·%d" (labelled nesting answer) index       pure (counted{_closing = kept}, closers ++ [indentedXml depth (printf "<answer meta=\"%s\">%s</answer>" (escapeXML naming) (escapeXMLText body))])     outer :: Int -> Nesting -> Nesting-    outer depth nesting = nesting{_openedAt = dropWhile ((>= depth) . fst) nesting._openedAt}+    outer depth nesting = nesting{_openedAt = dropWhile ((>= depth) . fst) nesting._openedAt, _sources = dropWhile (\(level, _, _) -> level > depth) nesting._sources}     labelled :: Nesting -> T.Text -> String-    labelled nesting spelling = printf "%s.%d" (T.unpack spelling) (opener nesting)+    labelled nesting spelling = printf "%s·%d" (T.unpack spelling) (opener nesting)     opener :: Nesting -> Int     opener nesting = maybe 0 snd (listToMaybe nesting._openedAt)     numbered :: Nesting -> (Int, Nesting)@@ -626,8 +737,16 @@ answer :: T.Text answer = "𝑛" +sigil :: T.Text+sigil = "𝛿"++found :: Either Int Bytes -> Maybe (Bytes, String) -> Maybe String+found (Right bytes) (Just (held, naming))+  | bytes == held = Just naming+found _ _ = Nothing+ alias :: Int -> Int -> Expression-alias firing index = ExMeta (T.pack (printf "n.%d.%d" firing index))+alias firing index = ExMeta (T.pack (printf "n·%d·%d" firing index))  dontSaveEval :: SaveEvalFunc dontSaveEval _ = pure ()@@ -649,7 +768,7 @@   where     sited :: Evaluation -> Maybe (Progress -> Progress, Expression)     sited (EvFiring _ _ _ site) = Just (\progress -> progress{_firings = progress._firings + 1}, site)-    sited (EvFormation _ _ site) = Just (\progress -> progress{_formations = progress._formations + 1}, site)+    sited (EvStarted _ Dataization site) = Just (\progress -> progress{_formations = progress._formations + 1}, site)     sited _ = Nothing     reported :: (Progress -> Progress, Expression) -> IO ()     reported (counted, site) = do@@ -658,6 +777,6 @@       if maybe True (\told -> now - told >= interval) progress._told         then do           locator <- render site-          logInfo (printf "Entered %d formations and fired %d λ functions in %.0fs, now at %s" progress._formations progress._firings (now - progress._began) locator)+          logInfo (printf "Started %d dataizations and fired %d λ functions in %.0fs, now at %s" progress._formations progress._firings (now - progress._began) locator)           writeIORef cursor progress{_told = Just now}         else writeIORef cursor progress
src/Evaluate.hs view
@@ -16,11 +16,11 @@ import Data.List.NonEmpty (NonEmpty (..)) import Data.Maybe (fromMaybe, isNothing, listToMaybe) import qualified Data.Text as T-import Deps (Evaluation (..), State (..))+import Deps (Evaluation (..), Judgment (Morphing), State (..), resited) import Engine (Engine (..)) import Lambdas (Lambda (..), Meta (..), joined, matched, minted, symbolized) import Matcher (MetaValue (..), Subst, combine, substEmpty, substSingle, substSlot)-import Morph (Answer, Firing (..), Kept (..), ReduceContext (..), ReduceException (..), Refused (..), Steps (..), admitted, charged, counted, deeper, isLambda, lambda, morphing, normalized, recalled, refused, remember, remembered, retained, settled, starved, unparked)+import Morph (Answer, Firing (..), Kept (..), ReduceContext (..), ReduceException (..), Refused (..), Steps (..), admitted, charged, counted, deeper, isLambda, lambda, morphing, normalized, opening, recalled, refused, remember, remembered, retained, settled, starved, unparked) import Printer (printFunction) import Rule (RuleContext (RuleContext), matchExpressionWithRule') import Text.Printf (printf)@@ -193,7 +193,7 @@       symbolic <- foldM mint bound fresh       built <- buildExpressionThrows entry._answer symbolic       ctx._saveEval (EvBuilt ctx._nesting built)-      (normal, state'') <- settled built univ state' ctx+      (normal, state'') <- settled built univ state' =<< opening Morphing ctx{_saveEval = ctx._saveEval . resited ctx._site built}       ctx._saveEval (EvAnswer ctx._nesting normal)       pure ((built, normal), state'')     mint :: Subst -> (Slot, Function) -> IO Subst
src/LaTeX.hs view
@@ -144,7 +144,7 @@   concat     [ printf "\\begin{%s}\n" (phiquation ctx)     , maybe "" (printf "\\label{%s}\n") _label-    , maybe "" (printf "\\phiExpression{%s} ") _expression+    , maybe "" (printf "\\phiExpression{%s} " . escaped) _expression     ]  body :: [String] -> [(a, Maybe (Judgment, String))] -> (Int -> a -> String) -> String@@ -159,7 +159,7 @@                   ++ maybe                     opening                     ( \(judgment, name) ->-                        if judgment == Contextualization+                        if judgment `elem` [Contextualization, Evaluation]                           then printf "%s %s" opening (relation judgment)                           else printf "%s %s[\\nameref{r:%s}]" opening (relation judgment) (escaped name)                     )@@ -262,6 +262,7 @@   toLaTeX EX_BYTES{..} = EX_BYTES (toLaTeX bytes)   toLaTeX EX_SINGLE{..} = EX_SINGLE (toLaTeX pair) SPACE (toLaTeX formation)   toLaTeX EX_STRING{..} = EX_STRING (T.unpack (toLaTeX (T.pack str))) tab rhos+  toLaTeX num@EX_NUMBER{} = EX_ATTR (toLaTeX (AT_LABEL (render num)))   toLaTeX expr = expr  instance ToLaTeX ATTRIBUTE where
src/Morph.hs view
@@ -11,7 +11,7 @@ -- SPDX-FileCopyrightText: Copyright (c) 2025 Objectionary.com -- SPDX-License-Identifier: MIT -module Morph (Answer, Deadline (..), Firing (..), Kept (..), ReduceContext (..), ReduceException (..), EvaluationFunc, FiringFunc, Memo (..), ReductionFunc, Morphed, Refused (..), Steps (..), Tally (..), admitted, boxed, charged, counted, deeper, emptyState, enter, entering, execBuildTerm, inferred, insideUniverse, isLambda, lambda, leadsTo, memoized, morph, morph', morphing, normalized, onward, parking, recalled, refused, remember, remembered, retained, settled, starved, tallied, timed, universed, unparked) where+module Morph (Answer, Deadline (..), Firing (..), Kept (..), ReduceContext (..), ReduceException (..), EvaluationFunc, FiringFunc, Memo (..), ReductionFunc, Morphed, Refused (..), Steps (..), Tally (..), admitted, boxed, charged, counted, deeper, emptyState, enter, entering, execBuildTerm, inferred, insideUniverse, isLambda, lambda, leadsTo, memoized, morph, morph', morphing, normalized, onward, opening, parking, recalled, refused, remember, remembered, retained, settled, starved, tallied, timed, universed, unparked) where  import AST import Builder (buildExpressionThrows, nameIn, pathOf)@@ -99,6 +99,7 @@   , _deadline :: Maybe Deadline   , _memo :: Maybe Memo   , _nesting :: Int+  , _opened :: Maybe (Int, Judgment, Expression)   , _depthSensitive :: Bool   , _shuffle :: Bool   , _partial :: Bool@@ -346,7 +347,7 @@   where     go :: Morphed -> Expression -> State -> ReduceContext -> IO (Morphed, State)     go (expr, seq) univ state caller = do-      ctx <- deeper =<< entering expr =<< universed univ caller{_judgment = Morphing}+      ctx <- opening Morphing =<< deeper =<< entering expr =<< universed univ caller{_judgment = Morphing}       parking seq state $ do         reached <- inferred expr univ state ctx ctx._engine._morphing         case reached of@@ -377,7 +378,7 @@  morph :: Expression -> State -> ReduceContext -> IO (Expression, [Rewritten], State) morph universe state caller@ReduceContext{..} = do-  ctx <- universed universe caller+  ctx <- opening Morphing =<< universed universe caller   expr <- locatedExpression _locator universe   result <- try (morph' (expr, (universe, Nothing) :| []) universe state ctx)   case result of@@ -421,7 +422,7 @@     go = step parts     step :: (Maybe Expression -> Frame -> Expression -> State -> ReduceContext -> IO (Expression, State)) -> Maybe Expression -> Maybe Attribute -> Frame -> Expression -> State -> ReduceContext -> IO (Expression, State)     step walk standing dispatched frame@(Frame world _ _ _) term state' caller = do-      let here = sited standing caller+      here <- maybe (pure caller) (\loc -> opening Morphing caller{_site = loc}) standing       ctx' <- deeper here       copy <- deferrable dispatched world term state' here       case copy of@@ -519,9 +520,6 @@       where         agreed :: (Expression, [Binding]) -> (Int, Int)         agreed (_, declared) = (length [attr | BiTau attr _ <- bds, BiVoid attr `elem` declared], length (filter (`elem` declared) bds))-    sited :: Maybe Expression -> ReduceContext -> ReduceContext-    sited Nothing caller = caller-    sited (Just loc) caller = caller{_site = loc}     parts :: Maybe Expression -> Frame -> Expression -> State -> ReduceContext -> IO (Expression, State)     parts _ _ term@(ExFormation bds) state' _       | any abstract bds = pure (term, state')@@ -764,6 +762,13 @@     extended attr normal = case ctx._universe of       Just (ExFormation bds) -> Just (ExFormation (BiTau attr normal : bds))       _ -> Nothing++opening :: Judgment -> ReduceContext -> IO ReduceContext+opening judgment ctx+  | ctx._opened == Just (ctx._nesting, judgment, ctx._site) = pure ctx{_judgment = judgment}+  | otherwise = do+      ctx._saveEval (EvStarted ctx._nesting judgment ctx._site)+      pure ctx{_judgment = judgment, _nesting = ctx._nesting + 1, _opened = Just (ctx._nesting + 1, judgment, ctx._site)}  settled :: Expression -> Expression -> State -> ReduceContext -> IO (Expression, State) settled term univ state ctx = do
src/XMIR.hs view
@@ -43,6 +43,7 @@ import Data.Version (showVersion) import Development.GitRev (gitHash) import Misc+import Parser (parseAttribute) import Paths_phino (version) import Printer import Text.Printf (printf)@@ -472,7 +473,9 @@         ('α' : _) -> throwIO (InvalidXMIRFormat "Formation child @name can't start with α" cur)         "φ" -> BiTau AtPhi <$> xmirToFormation derived cur (name : fqn)         "ρ" -> BiTau AtRho <$> xmirToFormation derived cur (name : fqn)-        _ -> BiTau (AtLabel (T.pack name)) <$> xmirToFormation derived cur (name : fqn)+        ('+' : test) -> toAttr test cur >> BiTau (AtLabel (T.pack name)) <$> xmirToFormation derived cur (name : fqn)+        ('-' : test) -> toAttr test cur >> BiTau (AtLabel (T.pack name)) <$> xmirToFormation derived cur (name : fqn)+        _ -> toAttr name cur >>= \attr -> BiTau attr <$> xmirToFormation derived cur (name : fqn)   | otherwise = do       name <- getAttr "name" cur       base <- getAttr "base" cur@@ -480,7 +483,9 @@         "φ" -> pure AtPhi         "ρ" -> pure AtRho         ('α' : _) -> throwIO (InvalidXMIRFormat "Formation child @name can't start with α" cur)-        _ -> pure (AtLabel (T.pack name))+        ('+' : test) -> toAttr test cur >> pure (AtLabel (T.pack name))+        ('-' : test) -> toAttr test cur >> pure (AtLabel (T.pack name))+        _ -> toAttr name cur       case base of         "∅" -> pure (BiVoid attr)         _ -> do@@ -650,6 +655,7 @@   ch : _     | ch `notElem` ['a' .. 'z'] -> throwIO (InvalidXMIRFormat (printf "The attribute '%s' must start with ['a'..'z']" attr) cur)     | '.' `elem` attr -> throwIO (InvalidXMIRFormat "Attribute can't contain dots" cur)+    | parseAttribute attr /= Right (AtLabel (T.pack attr)) -> throwIO (InvalidXMIRFormat (printf "The attribute '%s' is not a label the phi grammar reads" attr) cur)     | otherwise -> pure (AtLabel (T.pack attr))   _ -> throwIO (InvalidXMIRFormat (printf "Invalid attribute given: %s" attr) cur) 
src/Yaml.hs view
@@ -41,6 +41,13 @@     current :: [Key.Key]     current = KeyMap.keys v +validateKnownYamlKeys :: (MonadFail a) => Object -> [String] -> a ()+validateKnownYamlKeys v keys =+  let unknown = filter (\key -> key `notElem` map Key.fromString keys) (KeyMap.keys v)+   in case unknown of+        [] -> pure ()+        key : _ -> fail (printf "Unknown key '%s', expected one of: %s" (show key) (show keys))+ parseJSON' :: String -> (String -> Either String a) -> Value -> Parser a parseJSON' nm func =   withText@@ -183,7 +190,8 @@       )  instance FromJSON Rule where-  parseJSON value = do+  parseJSON value@(Object fields) = do+    validateKnownYamlKeys fields ["name", "label", "description", "pattern", "result", "e-match", "when", "having", "where"]     rule <-       genericParseJSON         defaultOptions@@ -234,6 +242,7 @@                 (unpack missing)                 field             )+  parseJSON value = genericParseJSON defaultOptions value  data Number   = MetaIndex Text
test/CLISpec.hs view
@@ -407,6 +407,11 @@           , ["--label option can stay together with --output=latex only"]           )         ,+          ( "with an unsafe --label and --output=latex"+          , ["rewrite", "--label=eq:bad%tag", "--output=latex"]+          , ["The --label option must contain only letters, numbers, colons, periods, underscores, and hyphens"]+          )+        ,           ( "with --compress and --output != latex"           , ["rewrite", "--compress", "--output=phi"]           , ["--compress option can stay together with --output=latex only"]@@ -625,11 +630,11 @@           [ unlines               [ "\\begin{phiquation}"               , "[["-              , "  |x\\char95{}o| -> Q . |z| ( |y| -> 5 ),"+              , "  |x\\char95{}o| -> Q . |z| ( |y| -> |5| ),"               , "  |q\\char36{}| -> T,"               , "  |w| -> \\phiTerminal{\\xi},"               , "  \\phiTerminal{\\rho} -> Q,"-              , "  @ -> 1,"+              , "  @ -> |1|,"               , "  |y| -> \"H\\char36{}\\char64{}\\char94{}M\","               , "  L> |Fu\\char95{}nc|"               , "]]{.}"@@ -643,7 +648,7 @@           ["rewrite", "--output=latex", "--sweet", "--nonumber", "--flat"]           [ unlines               [ "\\begin{phiquation*}"-              , "5 : |x|{.}"+              , "|5| : |x|{.}"               , "\\end{phiquation*}"               ]           ]@@ -665,18 +670,29 @@           ["rewrite", "--output=latex", "--sweet", "--flat", "--expression=foo"]           [ unlines               [ "\\begin{phiquation}"-              , "\\phiExpression{foo} 5 : |x|{.}"+              , "\\phiExpression{foo} |5| : |x|{.}"               , "\\end{phiquation}"               ]           ] +    it "escapes special characters in the LaTeX expression name" $+      withStdin "[[ x -> 5 ]]" $+        testCLISucceeded+          ["rewrite", "--output=latex", "--sweet", "--flat", "--expression=bad%tag"]+          [ unlines+              [ "\\begin{phiquation}"+              , "\\phiExpression{bad\\char37{}tag} |5| : |x|{.}"+              , "\\end{phiquation}"+              ]+          ]+     it "rewrite as LaTeX with label name" $       withStdin "[[ x -> 5 ]]" $         testCLISucceeded           ["rewrite", "--output=latex", "--sweet", "--flat", "--label=foo"]           [ unlines               [ "\\begin{phiquation}\n\\label{foo}"-              , "5 : |x|{.}"+              , "|5| : |x|{.}"               , "\\end{phiquation}"               ]           ]@@ -852,7 +868,7 @@           ["rewrite", "--normalize", "--sequence", "--flat", "--compress", "--output=latex", "--sweet"]           [ unlines               [ "\\begin{phiquation}"-              , "[[ |y| -> ?, |k| -> \\phinoMeet{1}{ 42 : |t| } ]] ( |y| -> \\phinoAgain{1} ) : |x| . |i| : |ex| \\phiNormalize[\\nameref{r:copy}]"+              , "[[ |y| -> ?, |k| -> \\phinoMeet{1}{ |42| : |t| } ]] ( |y| -> \\phinoAgain{1} ) : |x| . |i| : |ex| \\phiNormalize[\\nameref{r:copy}]"               , "  \\phiNormalize [[ |y| -> \\phinoAgain{1}, |k| -> \\phinoAgain{1} ]] : |x| . |i| : |ex| \\phiNormalize[\\nameref{r:stop}]"               , "  \\phiNormalize T : |ex|{.}"               , "\\end{phiquation}"@@ -865,8 +881,8 @@           ["rewrite", "--normalize", "--sequence", "--flat", "--compress", "--output=latex", "--sweet", "--meet-popularity=70"]           [ unlines               [ "\\begin{phiquation}"-              , "[[ |y| -> ?, |k| -> 42 : |t| ]] ( |y| -> 42 : |t| ) : |x| . |i| : |ex| \\phiNormalize[\\nameref{r:copy}]"-              , "  \\phiNormalize [[ |y| -> 42 : |t|, |k| -> 42 : |t| ]] : |x| . |i| : |ex| \\phiNormalize[\\nameref{r:stop}]"+              , "[[ |y| -> ?, |k| -> |42| : |t| ]] ( |y| -> |42| : |t| ) : |x| . |i| : |ex| \\phiNormalize[\\nameref{r:copy}]"+              , "  \\phiNormalize [[ |y| -> |42| : |t|, |k| -> |42| : |t| ]] : |x| . |i| : |ex| \\phiNormalize[\\nameref{r:stop}]"               , "  \\phiNormalize T : |ex|{.}"               , "\\end{phiquation}"               ]@@ -878,8 +894,8 @@           ["rewrite", "--normalize", "--sequence", "--flat", "--compress", "--output=latex", "--sweet", "--meet-length=32"]           [ unlines               [ "\\begin{phiquation}"-              , "[[ |y| -> ?, |k| -> 42 : |t| ]] ( |y| -> 42 : |t| ) : |x| . |i| : |ex| \\phiNormalize[\\nameref{r:copy}]"-              , "  \\phiNormalize [[ |y| -> 42 : |t|, |k| -> 42 : |t| ]] : |x| . |i| : |ex| \\phiNormalize[\\nameref{r:stop}]"+              , "[[ |y| -> ?, |k| -> |42| : |t| ]] ( |y| -> |42| : |t| ) : |x| . |i| : |ex| \\phiNormalize[\\nameref{r:copy}]"+              , "  \\phiNormalize [[ |y| -> |42| : |t|, |k| -> |42| : |t| ]] : |x| . |i| : |ex| \\phiNormalize[\\nameref{r:stop}]"               , "  \\phiNormalize T : |ex|{.}"               , "\\end{phiquation}"               ]@@ -891,8 +907,8 @@           ["rewrite", "--normalize", "--sequence", "--flat", "--output=latex", "--sweet", "--focus=Q.ex"]           [ unlines               [ "\\begin{phiquation}"-              , "[[ |y| -> ?, |k| -> 42 : |t| ]] ( |y| -> 42 : |t| ) : |x| . |i| \\phiNormalize[\\nameref{r:copy}]"-              , "  \\phiNormalize [[ |y| -> 42 : |t|, |k| -> 42 : |t| ]] : |x| . |i| \\phiNormalize[\\nameref{r:stop}]"+              , "[[ |y| -> ?, |k| -> |42| : |t| ]] ( |y| -> |42| : |t| ) : |x| . |i| \\phiNormalize[\\nameref{r:copy}]"+              , "  \\phiNormalize [[ |y| -> |42| : |t|, |k| -> |42| : |t| ]] : |x| . |i| \\phiNormalize[\\nameref{r:stop}]"               , "  \\phiNormalize T{.}"               , "\\end{phiquation}"               ]@@ -1270,11 +1286,11 @@               []           records <- readProtocol path           lines records-            `shouldBe` [ "𝔻(Φ.t)"-                       , "  applied(𝑛.0.1) := Φ.cyc( x ↦ ⟦⟧ )  # 𝕄(Φ.t)"-                       , "  formation(𝑛.0.1)  # 𝔻(Φ.t)"-                       , "    applied(𝑛.0.2) := Φ.cyc( x ↦ ⟦⟧ )  # 𝕄(Φ.t)"-                       , "    looped(𝑛.0.2)  # 𝔻(Φ.t), proven"+            `shouldBe` [ "𝔻(Φ.t):"+                       , "  𝕄(Φ.t):"+                       , "    𝑛·0·1 := Φ.cyc( x ↦ ⟦⟧ )"+                       , "    𝑛·0·2 := Φ.cyc( x ↦ ⟦⟧ )"+                       , "  looped(𝑛·0·2)  # proven"                        ]        it "writes the cut to the XML protocol with the formation in an element of its own" $@@ -1288,11 +1304,11 @@           lines records             `shouldBe` [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"                        , "<dataize at=\"Φ.t\">"-                       , "  <applied meta=\"𝑛.0.1\" by=\"morph\" at=\"Φ.t\" of=\"Φ.cyc\"><attr name=\"x\">⟦⟧</attr></applied>"-                       , "  <formation at=\"Φ.t\" term=\"𝑛.0.1\">"-                       , "    <applied meta=\"𝑛.0.2\" by=\"morph\" at=\"Φ.t\" of=\"Φ.cyc\"><attr name=\"x\">⟦⟧</attr></applied>"-                       , "    <looped by=\"dataize\" match=\"proven\" at=\"Φ.t\"><e>𝑛.0.2</e></looped>"-                       , "  </formation>"+                       , "  <morph at=\"Φ.t\">"+                       , "    <applied meta=\"𝑛·0·1\" by=\"morph\" at=\"Φ.t\" of=\"Φ.cyc\"><attr name=\"x\">⟦⟧</attr></applied>"+                       , "    <applied meta=\"𝑛·0·2\" by=\"morph\" at=\"Φ.t\" of=\"Φ.cyc\"><attr name=\"x\">⟦⟧</attr></applied>"+                       , "  </morph>"+                       , "  <looped by=\"dataize\" match=\"proven\" at=\"Φ.t\"><e>𝑛·0·2</e></looped>"                        , "</dataize>"                        ] @@ -1304,7 +1320,7 @@               ["dataize", "--locator=Q.t", "--acyclic=plausible", "--partial", "--protocol=" ++ path, "--sweet", "--hide-rho", "--flat", "--quiet"]               []           records <- readProtocol path-          lines records `shouldContain` ["    looped(𝑛.0.2)  # 𝔻(Φ.t), plausible"]+          lines records `shouldContain` ["  looped(𝑛·0·2)  # plausible"]        it "refuses the flag without a mode" $         withStdin "⟦ t ↦ ⟦ Δ ⤍ 01-02 ⟧ ⟧" $@@ -1358,7 +1374,7 @@       withStdin "[[ @ -> [[ @ -> $.c.plus( 32.0 ), c -> 25.0 ]], bytes ↦ ⟦ φ ↦ ∅ ⟧, number(φ) -> [[ plus -> [[ ^ -> ?, x -> ?, L> L_number_plus ]] ]] ]]" $         testCLISucceeded           ["dataize", symbolic, "--output=latex", "--sweet", "--nonumber", "--compress", "--canonize", "--meet-prefix=dataization", "--sequence", "--flat", "--quiet", "--hide=Q.bytes", "--hide=Q.number", "--locator=Q.@", "--focus=Q.@", "--meet-length=5", "--meet-popularity=1"]-          ["\\phinoMeet{dataization:1}{ [[ @ -> |c| . |plus| ( 32 ), |c| -> 25 ]] } \\phiContextualize"]+          ["\\phinoMeet{dataization:1}{ [[ @ -> |c| . |plus| ( |32| ), |c| -> |25| ]] } \\phiContextualize"]      it "compresses a canonized whole-expression sequence into a meet" $       withStdin "[[ @ -> [[ @ -> $.c.plus( 32.0 ), c -> 25.0 ]], bytes ↦ ⟦ φ ↦ ∅ ⟧, number(φ) -> [[ plus -> [[ ^ -> ?, x -> ?, L> L_number_plus ]] ]] ]]" $@@ -1380,23 +1396,24 @@      describe "--abridged" $ do       let wide = "⟦ t ↦ ⟦ φ ↦ ⟦ Δ ⤍ 01-02 ⟧, anfang ↦ ξ.schluss, mitte ↦ ξ.anfang, schluss ↦ ξ.mitte, rand ↦ ξ.schluss ⟧ ⟧"+          stuck = "⟦ t ↦ ⟦ λ ⤍ L_weit, anfang ↦ ξ.schluss, mitte ↦ ξ.anfang, schluss ↦ ξ.mitte, rand ↦ ξ.schluss ⟧ ⟧"       it "folds a long formation in the text protocol" $         withTempFile "protocolXXXXXX.txt" $ \(path, stream) -> do           hClose stream-          withStdin wide $-            testCLISucceeded ["dataize", "--locator=Q.t", "--protocol=" ++ path, "--abridged", "--sweet", "--hide-rho", "--quiet"] []+          withStdin stuck $+            testCLISucceeded ["dataize", "--locator=Q.t", "--partial", "--protocol=" ++ path, "--abridged", "--sweet", "--hide-rho", "--quiet"] []           records <- readProtocol path-          lines records `shouldContain` ["  formation(⟦ φ ↦ 01-02:Δ, +4 ⟧)  # 𝔻(Φ.t)"]+          lines records `shouldContain` ["  unanswered(L_weit)  # 𝔻(⟦ λ ⤍ L_weit, +4 ⟧)"]       it "folds a long formation in the XML protocol" $         withTempFile "protocolXXXXXX.xml" $ \(path, stream) -> do           hClose stream-          withStdin wide $-            testCLISucceeded ["dataize", "--locator=Q.t", "--protocol=" ++ path, "--abridged", "--sweet", "--hide-rho", "--quiet"] []+          withStdin stuck $+            testCLISucceeded ["dataize", "--locator=Q.t", "--partial", "--protocol=" ++ path, "--abridged", "--sweet", "--hide-rho", "--quiet"] []           records <- readProtocol path-          lines records `shouldContain` ["  <formation at=\"Φ.t\" term=\"⟦ φ ↦ 01-02:Δ, +4 ⟧\">"]+          lines records `shouldContain` ["  <unanswered λ=\"L_weit\" by=\"dataize\">⟦ λ ⤍ L_weit, +4 ⟧</unanswered>"]       forM_-        [ ("textXXXXXX.txt", "    𝛿1.1 := 01-02-..(8b)..-0B-0C  # 𝔻(ξ.arg)")-        , ("XMLXXXXXX.xml", "    <bind meta=\"𝛿1.1\">01-02-..(8b)..-0B-0C</bind>")+        [ ("textXXXXXX.txt", "      𝛿·1·1 := 01-02-..(8b)..-0B-0C")+        , ("XMLXXXXXX.xml", "      <delta meta=\"𝛿·1·1\">01-02-..(8b)..-0B-0C</delta>")         ]         ( \(template, line) ->             it ("cuts a long datum a firing came down to under --abridged-data, as " ++ line) $@@ -1409,8 +1426,8 @@                 lines records `shouldContain` [line]         )       forM_-        [ ("textXXXXXX.txt", "    𝛿1.1 := 30-31-32-33-34-35-36-37-38-39-41-42-43-44-45-46  # 𝔻(ξ.arg)")-        , ("XMLXXXXXX.xml", "    <bind meta=\"𝛿1.1\">30-31-32-33-34-35-36-37-38-39-41-42-43-44-45-46</bind>")+        [ ("textXXXXXX.txt", "      𝛿·1·1 := 30-31-32-33-34-35-36-37-38-39-41-42-43-44-45-46")+        , ("XMLXXXXXX.xml", "      <delta meta=\"𝛿·1·1\">30-31-32-33-34-35-36-37-38-39-41-42-43-44-45-46</delta>")         ]         ( \(template, line) ->             it ("keeps a long datum a firing came down to whole without --abridged-data, as " ++ line) $@@ -1425,17 +1442,17 @@       it "folds a long formation under the width given as the value" $         withTempFile "protocolXXXXXX.txt" $ \(path, stream) -> do           hClose stream-          withStdin wide $-            testCLISucceeded ["dataize", "--locator=Q.t", "--protocol=" ++ path, "--abridged=64", "--sweet", "--hide-rho", "--quiet"] []+          withStdin stuck $+            testCLISucceeded ["dataize", "--locator=Q.t", "--partial", "--protocol=" ++ path, "--abridged=64", "--sweet", "--hide-rho", "--quiet"] []           records <- readProtocol path-          lines records `shouldContain` ["  formation(⟦ φ ↦ 01-02:Δ, +4 ⟧)  # 𝔻(Φ.t)"]+          lines records `shouldContain` ["  unanswered(L_weit)  # 𝔻(⟦ λ ⤍ L_weit, +4 ⟧)"]       it "keeps a formation whole under a width it fits in" $         withTempFile "protocolXXXXXX.txt" $ \(path, stream) -> do           hClose stream-          withStdin wide $-            testCLISucceeded ["dataize", "--locator=Q.t", "--protocol=" ++ path, "--abridged=200", "--sweet", "--hide-rho", "--quiet"] []+          withStdin stuck $+            testCLISucceeded ["dataize", "--locator=Q.t", "--partial", "--protocol=" ++ path, "--abridged=200", "--sweet", "--hide-rho", "--quiet"] []           records <- readProtocol path-          lines records `shouldContain` ["  formation(⟦ φ ↦ 01-02:Δ, anfang ↦ schluss, mitte ↦ anfang, schluss ↦ mitte, rand ↦ schluss ⟧)  # 𝔻(Φ.t)"]+          lines records `shouldContain` ["  unanswered(L_weit)  # 𝔻(⟦ λ ⤍ L_weit, anfang ↦ schluss, mitte ↦ anfang, schluss ↦ mitte, rand ↦ schluss ⟧)"]       it "refuses a width that is not a number" $         withStdin wide $           testCLIFailed ["dataize", "--locator=Q.t", "--protocol=breit.txt", "--abridged=breit"] ["cannot parse value `breit'"]@@ -1465,7 +1482,7 @@           withStdin "[[ D> 01- ]]" $             testCLISucceeded ["dataize", "--protocol=" ++ path, "--quiet"] []           records <- readProtocol path-          records `shouldBe` "𝔻(Φ)\n"+          records `shouldBe` "𝔻(Φ):\n  𝛿·0·1 := 01-\n"        it "closes the protocol with its msec on the third line from the end" $         withTempFile "protocolXXXXXX.txt" $ \(path, stream) -> do@@ -1506,25 +1523,27 @@             testCLISucceeded ["dataize", symbolic, "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []           records <- readProtocol path           lines records-            `shouldBe` [ "𝔻(Φ)"-                       , "  formation(⟦ bytes(φ) ↦ ⟦⟧, number(φ) ↦ ⟦ plus(x) ↦ L_number_plus:λ ⟧, φ ↦ 5.plus( 6 ) ⟧)  # 𝔻(Φ)"-                       , "    applied(𝑛.0.1) := 5  # 𝕄(Φ)"-                       , "    applied(𝑛.0.2) := 𝑛.0.1.plus( x ↦ 6 )  # 𝕄(Φ)"-                       , "    𝔼(L_number_plus)  # 𝔻(Φ)"-                       , "      applied(𝑛.1.1) := 5  # 𝕄(Φ.a🌵0)"-                       , "      formation(𝑛.1.1)  # 𝔻(Φ.a🌵0)"-                       , "        applied(𝑛.1.2) := Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵0)"-                       , "        formation(𝑛.1.2)  # 𝔻(Φ.a🌵0)"-                       , "      𝛿1.1 := 40-14-00-00-00-00-00-00  # 𝔻(ξ.ρ)"-                       , "      applied(𝑛.1.3) := 6  # 𝕄(Φ.a🌵1)"-                       , "      formation(𝑛.1.3)  # 𝔻(Φ.a🌵1)"-                       , "        applied(𝑛.1.4) := Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵1)"-                       , "        formation(𝑛.1.4)  # 𝔻(Φ.a🌵1)"-                       , "      𝛿2.1 := 40-18-00-00-00-00-00-00  # 𝔻(ξ.x)"-                       , "      𝑛.1.5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛"-                       , "      applied(𝑛.1.6) := Φ.number( φ ↦ 𝜎1:λ )  # 𝕄(Φ)"-                       , "      𝑛.1.7 := 𝑛.1.6  # 𝕄(𝑛.1.5)"-                       , "    formation(𝑛.1.6)  # 𝔻(Φ)"+            `shouldBe` [ "𝔻(Φ):"+                       , "  𝕄(Φ):"+                       , "    𝑛·0·1 := 5"+                       , "    𝑛·0·2 := 𝑛·0·1.plus( x ↦ 6 )"+                       , "  𝔼(L_number_plus):"+                       , "    𝔻(Φ.a🌵0):"+                       , "      𝕄(Φ.a🌵0):"+                       , "        𝑛·1·1 := 5"+                       , "        𝑛·1·2 := Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )"+                       , "      𝛿·1·1 := 40-14-00-00-00-00-00-00  # 5.0"+                       , "    𝛿1·1 := 𝛿·1·1  # 𝔻(ξ.ρ)"+                       , "    𝔻(Φ.a🌵1):"+                       , "      𝕄(Φ.a🌵1):"+                       , "        𝑛·1·3 := 6"+                       , "        𝑛·1·4 := Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )"+                       , "      𝛿·1·2 := 40-18-00-00-00-00-00-00  # 6.0"+                       , "    𝛿2·1 := 𝛿·1·2  # 𝔻(ξ.x)"+                       , "    𝑛·1·5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛"+                       , "    𝕄(𝑛·1·5):"+                       , "      𝑛·1·6 := Φ.number( φ ↦ 𝜎1:λ )"+                       , "    𝑛·1·7 := 𝑛·1·6  # 𝕄(𝑛·1·5)"                        ]        it "numbers the firings of one entry apart and names the symbol between them" $@@ -1534,38 +1553,43 @@             testCLISucceeded ["dataize", symbolic, "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []           records <- readProtocol path           lines records-            `shouldBe` [ "𝔻(Φ)"-                       , "  formation(⟦ bytes(φ) ↦ ⟦⟧, number(φ) ↦ ⟦ plus(x) ↦ L_number_plus:λ ⟧, φ ↦ 5.plus( 6 ).plus( 7 ) ⟧)  # 𝔻(Φ)"-                       , "    applied(𝑛.0.1) := 5  # 𝕄(Φ)"-                       , "    applied(𝑛.0.2) := 𝑛.0.1.plus( x ↦ 6 )  # 𝕄(Φ)"-                       , "    𝔼(L_number_plus)  # 𝕄(Φ)"-                       , "      applied(𝑛.1.1) := 5  # 𝕄(Φ.a🌵0)"-                       , "      formation(𝑛.1.1)  # 𝔻(Φ.a🌵0)"-                       , "        applied(𝑛.1.2) := Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵0)"-                       , "        formation(𝑛.1.2)  # 𝔻(Φ.a🌵0)"-                       , "      𝛿1.1 := 40-14-00-00-00-00-00-00  # 𝔻(ξ.ρ)"-                       , "      applied(𝑛.1.3) := 6  # 𝕄(Φ.a🌵1)"-                       , "      formation(𝑛.1.3)  # 𝔻(Φ.a🌵1)"-                       , "        applied(𝑛.1.4) := Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵1)"-                       , "        formation(𝑛.1.4)  # 𝔻(Φ.a🌵1)"-                       , "      𝛿2.1 := 40-18-00-00-00-00-00-00  # 𝔻(ξ.x)"-                       , "      𝑛.1.5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛"-                       , "      applied(𝑛.1.6) := Φ.number( φ ↦ 𝜎1:λ )  # 𝕄(Φ)"-                       , "      𝑛.1.7 := 𝑛.1.6  # 𝕄(𝑛.1.5)"-                       , "    applied(𝑛.0.3) := 𝑛.1.6.plus( x ↦ 7 )  # 𝕄(Φ)"-                       , "    𝔼(L_number_plus)  # 𝔻(Φ)"-                       , "      applied(𝑛.2.1) := Φ.number( φ ↦ 𝜎1:λ )  # 𝕄(Φ.a🌵2)"-                       , "      formation(𝑛.2.1)  # 𝔻(Φ.a🌵2)"-                       , "      𝛿1.2 := 𝔻(𝜎1:λ)  # 𝔻(ξ.ρ)"-                       , "      applied(𝑛.2.2) := 7  # 𝕄(Φ.a🌵3)"-                       , "      formation(𝑛.2.2)  # 𝔻(Φ.a🌵3)"-                       , "        applied(𝑛.2.3) := Φ.bytes( φ ↦ 40-1C-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵3)"-                       , "        formation(𝑛.2.3)  # 𝔻(Φ.a🌵3)"-                       , "      𝛿2.2 := 40-1C-00-00-00-00-00-00  # 𝔻(ξ.x)"-                       , "      𝑛.2.4 := Φ.number( φ ↦ 𝜎2:λ )  # 𝑛"-                       , "      applied(𝑛.2.5) := Φ.number( φ ↦ 𝜎2:λ )  # 𝕄(Φ)"-                       , "      𝑛.2.6 := 𝑛.2.5  # 𝕄(𝑛.2.4)"-                       , "    formation(𝑛.2.5)  # 𝔻(Φ)"+            `shouldBe` [ "𝔻(Φ):"+                       , "  𝕄(Φ):"+                       , "    𝑛·0·1 := 5"+                       , "    𝑛·0·2 := 𝑛·0·1.plus( x ↦ 6 )"+                       , "    𝔼(L_number_plus):"+                       , "      𝔻(Φ.a🌵0):"+                       , "        𝕄(Φ.a🌵0):"+                       , "          𝑛·1·1 := 5"+                       , "          𝑛·1·2 := Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )"+                       , "        𝛿·1·1 := 40-14-00-00-00-00-00-00  # 5.0"+                       , "      𝛿1·1 := 𝛿·1·1  # 𝔻(ξ.ρ)"+                       , "      𝔻(Φ.a🌵1):"+                       , "        𝕄(Φ.a🌵1):"+                       , "          𝑛·1·3 := 6"+                       , "          𝑛·1·4 := Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )"+                       , "        𝛿·1·2 := 40-18-00-00-00-00-00-00  # 6.0"+                       , "      𝛿2·1 := 𝛿·1·2  # 𝔻(ξ.x)"+                       , "      𝑛·1·5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛"+                       , "      𝕄(𝑛·1·5):"+                       , "        𝑛·1·6 := Φ.number( φ ↦ 𝜎1:λ )"+                       , "      𝑛·1·7 := 𝑛·1·6  # 𝕄(𝑛·1·5)"+                       , "    𝑛·0·3 := 𝑛·1·6.plus( x ↦ 7 )"+                       , "  𝔼(L_number_plus):"+                       , "    𝔻(Φ.a🌵2):"+                       , "      𝕄(Φ.a🌵2):"+                       , "        𝑛·2·1 := Φ.number( φ ↦ 𝜎1:λ )"+                       , "    𝛿1·2 := 𝔻(𝜎1:λ)  # 𝔻(ξ.ρ)"+                       , "    𝔻(Φ.a🌵3):"+                       , "      𝕄(Φ.a🌵3):"+                       , "        𝑛·2·2 := 7"+                       , "        𝑛·2·3 := Φ.bytes( φ ↦ 40-1C-00-00-00-00-00-00:Δ )"+                       , "      𝛿·2·1 := 40-1C-00-00-00-00-00-00  # 7.0"+                       , "    𝛿2·2 := 𝛿·2·1  # 𝔻(ξ.x)"+                       , "    𝑛·2·4 := Φ.number( φ ↦ 𝜎2:λ )  # 𝑛"+                       , "    𝕄(𝑛·2·4):"+                       , "      𝑛·2·5 := Φ.number( φ ↦ 𝜎2:λ )"+                       , "    𝑛·2·6 := 𝑛·2·5  # 𝕄(𝑛·2·4)"                        ]        it "numbers the firings of different entries apart" $@@ -1575,38 +1599,43 @@             testCLISucceeded ["dataize", symbolic, "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []           records <- readProtocol path           lines records-            `shouldBe` [ "𝔻(Φ)"-                       , "  formation(⟦ bytes(φ) ↦ ⟦⟧, number(φ) ↦ ⟦ plus(x) ↦ L_number_plus:λ, times(x) ↦ L_number_times:λ ⟧, φ ↦ 5.plus( 6 ).times( 7 ) ⟧)  # 𝔻(Φ)"-                       , "    applied(𝑛.0.1) := 5  # 𝕄(Φ)"-                       , "    applied(𝑛.0.2) := 𝑛.0.1.plus( x ↦ 6 )  # 𝕄(Φ)"-                       , "    𝔼(L_number_plus)  # 𝕄(Φ)"-                       , "      applied(𝑛.1.1) := 5  # 𝕄(Φ.a🌵0)"-                       , "      formation(𝑛.1.1)  # 𝔻(Φ.a🌵0)"-                       , "        applied(𝑛.1.2) := Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵0)"-                       , "        formation(𝑛.1.2)  # 𝔻(Φ.a🌵0)"-                       , "      𝛿1.1 := 40-14-00-00-00-00-00-00  # 𝔻(ξ.ρ)"-                       , "      applied(𝑛.1.3) := 6  # 𝕄(Φ.a🌵1)"-                       , "      formation(𝑛.1.3)  # 𝔻(Φ.a🌵1)"-                       , "        applied(𝑛.1.4) := Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵1)"-                       , "        formation(𝑛.1.4)  # 𝔻(Φ.a🌵1)"-                       , "      𝛿2.1 := 40-18-00-00-00-00-00-00  # 𝔻(ξ.x)"-                       , "      𝑛.1.5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛"-                       , "      applied(𝑛.1.6) := Φ.number( φ ↦ 𝜎1:λ )  # 𝕄(Φ)"-                       , "      𝑛.1.7 := 𝑛.1.6  # 𝕄(𝑛.1.5)"-                       , "    applied(𝑛.0.3) := 𝑛.1.6.times( x ↦ 7 )  # 𝕄(Φ)"-                       , "    𝔼(L_number_times)  # 𝔻(Φ)"-                       , "      applied(𝑛.2.1) := Φ.number( φ ↦ 𝜎1:λ )  # 𝕄(Φ.a🌵2)"-                       , "      formation(𝑛.2.1)  # 𝔻(Φ.a🌵2)"-                       , "      𝛿1.2 := 𝔻(𝜎1:λ)  # 𝔻(ξ.ρ)"-                       , "      applied(𝑛.2.2) := 7  # 𝕄(Φ.a🌵3)"-                       , "      formation(𝑛.2.2)  # 𝔻(Φ.a🌵3)"-                       , "        applied(𝑛.2.3) := Φ.bytes( φ ↦ 40-1C-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵3)"-                       , "        formation(𝑛.2.3)  # 𝔻(Φ.a🌵3)"-                       , "      𝛿2.2 := 40-1C-00-00-00-00-00-00  # 𝔻(ξ.x)"-                       , "      𝑛.2.4 := Φ.number( φ ↦ 𝜎2:λ )  # 𝑛"-                       , "      applied(𝑛.2.5) := Φ.number( φ ↦ 𝜎2:λ )  # 𝕄(Φ)"-                       , "      𝑛.2.6 := 𝑛.2.5  # 𝕄(𝑛.2.4)"-                       , "    formation(𝑛.2.5)  # 𝔻(Φ)"+            `shouldBe` [ "𝔻(Φ):"+                       , "  𝕄(Φ):"+                       , "    𝑛·0·1 := 5"+                       , "    𝑛·0·2 := 𝑛·0·1.plus( x ↦ 6 )"+                       , "    𝔼(L_number_plus):"+                       , "      𝔻(Φ.a🌵0):"+                       , "        𝕄(Φ.a🌵0):"+                       , "          𝑛·1·1 := 5"+                       , "          𝑛·1·2 := Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )"+                       , "        𝛿·1·1 := 40-14-00-00-00-00-00-00  # 5.0"+                       , "      𝛿1·1 := 𝛿·1·1  # 𝔻(ξ.ρ)"+                       , "      𝔻(Φ.a🌵1):"+                       , "        𝕄(Φ.a🌵1):"+                       , "          𝑛·1·3 := 6"+                       , "          𝑛·1·4 := Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )"+                       , "        𝛿·1·2 := 40-18-00-00-00-00-00-00  # 6.0"+                       , "      𝛿2·1 := 𝛿·1·2  # 𝔻(ξ.x)"+                       , "      𝑛·1·5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛"+                       , "      𝕄(𝑛·1·5):"+                       , "        𝑛·1·6 := Φ.number( φ ↦ 𝜎1:λ )"+                       , "      𝑛·1·7 := 𝑛·1·6  # 𝕄(𝑛·1·5)"+                       , "    𝑛·0·3 := 𝑛·1·6.times( x ↦ 7 )"+                       , "  𝔼(L_number_times):"+                       , "    𝔻(Φ.a🌵2):"+                       , "      𝕄(Φ.a🌵2):"+                       , "        𝑛·2·1 := Φ.number( φ ↦ 𝜎1:λ )"+                       , "    𝛿1·2 := 𝔻(𝜎1:λ)  # 𝔻(ξ.ρ)"+                       , "    𝔻(Φ.a🌵3):"+                       , "      𝕄(Φ.a🌵3):"+                       , "        𝑛·2·2 := 7"+                       , "        𝑛·2·3 := Φ.bytes( φ ↦ 40-1C-00-00-00-00-00-00:Δ )"+                       , "      𝛿·2·1 := 40-1C-00-00-00-00-00-00  # 7.0"+                       , "    𝛿2·2 := 𝛿·2·1  # 𝔻(ξ.x)"+                       , "    𝑛·2·4 := Φ.number( φ ↦ 𝜎2:λ )  # 𝑛"+                       , "    𝕄(𝑛·2·4):"+                       , "      𝑛·2·5 := Φ.number( φ ↦ 𝜎2:λ )"+                       , "    𝑛·2·6 := 𝑛·2·5  # 𝕄(𝑛·2·4)"                        ]        it "nests the firing an operand of another firing brought down" $@@ -1616,38 +1645,43 @@             testCLISucceeded ["dataize", symbolic, "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []           records <- readProtocol path           lines records-            `shouldBe` [ "𝔻(Φ)"-                       , "  formation(⟦ bytes(φ) ↦ ⟦⟧, number(φ) ↦ ⟦ plus(x) ↦ L_number_plus:λ ⟧, φ ↦ 5.plus( 6.plus( 7 ) ) ⟧)  # 𝔻(Φ)"-                       , "    applied(𝑛.0.1) := 5  # 𝕄(Φ)"-                       , "    applied(𝑛.0.2) := 𝑛.0.1.plus( x ↦ 6.plus( 7 ) )  # 𝕄(Φ)"-                       , "    𝔼(L_number_plus)  # 𝔻(Φ)"-                       , "      applied(𝑛.1.1) := 5  # 𝕄(Φ.a🌵0)"-                       , "      formation(𝑛.1.1)  # 𝔻(Φ.a🌵0)"-                       , "        applied(𝑛.1.2) := Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵0)"-                       , "        formation(𝑛.1.2)  # 𝔻(Φ.a🌵0)"-                       , "      𝛿1.1 := 40-14-00-00-00-00-00-00  # 𝔻(ξ.ρ)"-                       , "      applied(𝑛.1.3) := 6  # 𝕄(Φ.a🌵1)"-                       , "      applied(𝑛.1.4) := 𝑛.1.3.plus( x ↦ 7 )  # 𝕄(Φ.a🌵1)"-                       , "      𝔼(L_number_plus)  # 𝔻(Φ.a🌵1)"-                       , "        applied(𝑛.2.1) := 6  # 𝕄(Φ.a🌵2)"-                       , "        formation(𝑛.2.1)  # 𝔻(Φ.a🌵2)"-                       , "          applied(𝑛.2.2) := Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵2)"-                       , "          formation(𝑛.2.2)  # 𝔻(Φ.a🌵2)"-                       , "        𝛿1.2 := 40-18-00-00-00-00-00-00  # 𝔻(ξ.ρ)"-                       , "        applied(𝑛.2.3) := 7  # 𝕄(Φ.a🌵3)"-                       , "        formation(𝑛.2.3)  # 𝔻(Φ.a🌵3)"-                       , "          applied(𝑛.2.4) := Φ.bytes( φ ↦ 40-1C-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵3)"-                       , "          formation(𝑛.2.4)  # 𝔻(Φ.a🌵3)"-                       , "        𝛿2.2 := 40-1C-00-00-00-00-00-00  # 𝔻(ξ.x)"-                       , "        𝑛.2.5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛"-                       , "        applied(𝑛.2.6) := Φ.number( φ ↦ 𝜎1:λ )  # 𝕄(Φ.a🌵1)"-                       , "        𝑛.2.7 := 𝑛.2.6  # 𝕄(𝑛.2.5)"-                       , "      formation(𝑛.2.6)  # 𝔻(Φ.a🌵1)"-                       , "      𝛿2.1 := 𝔻(𝜎1:λ)  # 𝔻(ξ.x)"-                       , "      𝑛.1.5 := Φ.number( φ ↦ 𝜎2:λ )  # 𝑛"-                       , "      applied(𝑛.1.6) := Φ.number( φ ↦ 𝜎2:λ )  # 𝕄(Φ)"-                       , "      𝑛.1.7 := 𝑛.1.6  # 𝕄(𝑛.1.5)"-                       , "    formation(𝑛.1.6)  # 𝔻(Φ)"+            `shouldBe` [ "𝔻(Φ):"+                       , "  𝕄(Φ):"+                       , "    𝑛·0·1 := 5"+                       , "    𝑛·0·2 := 𝑛·0·1.plus( x ↦ 6.plus( 7 ) )"+                       , "  𝔼(L_number_plus):"+                       , "    𝔻(Φ.a🌵0):"+                       , "      𝕄(Φ.a🌵0):"+                       , "        𝑛·1·1 := 5"+                       , "        𝑛·1·2 := Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )"+                       , "      𝛿·1·1 := 40-14-00-00-00-00-00-00  # 5.0"+                       , "    𝛿1·1 := 𝛿·1·1  # 𝔻(ξ.ρ)"+                       , "    𝔻(Φ.a🌵1):"+                       , "      𝕄(Φ.a🌵1):"+                       , "        𝑛·1·3 := 6"+                       , "        𝑛·1·4 := 𝑛·1·3.plus( x ↦ 7 )"+                       , "      𝔼(L_number_plus):"+                       , "        𝔻(Φ.a🌵2):"+                       , "          𝕄(Φ.a🌵2):"+                       , "            𝑛·2·1 := 6"+                       , "            𝑛·2·2 := Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )"+                       , "          𝛿·2·1 := 40-18-00-00-00-00-00-00  # 6.0"+                       , "        𝛿1·2 := 𝛿·2·1  # 𝔻(ξ.ρ)"+                       , "        𝔻(Φ.a🌵3):"+                       , "          𝕄(Φ.a🌵3):"+                       , "            𝑛·2·3 := 7"+                       , "            𝑛·2·4 := Φ.bytes( φ ↦ 40-1C-00-00-00-00-00-00:Δ )"+                       , "          𝛿·2·2 := 40-1C-00-00-00-00-00-00  # 7.0"+                       , "        𝛿2·2 := 𝛿·2·2  # 𝔻(ξ.x)"+                       , "        𝑛·2·5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛"+                       , "        𝕄(𝑛·2·5):"+                       , "          𝑛·2·6 := Φ.number( φ ↦ 𝜎1:λ )"+                       , "        𝑛·2·7 := 𝑛·2·6  # 𝕄(𝑛·2·5)"+                       , "    𝛿2·1 := 𝔻(𝜎1:λ)  # 𝔻(ξ.x)"+                       , "    𝑛·1·5 := Φ.number( φ ↦ 𝜎2:λ )  # 𝑛"+                       , "    𝕄(𝑛·1·5):"+                       , "      𝑛·1·6 := Φ.number( φ ↦ 𝜎2:λ )"+                       , "    𝑛·1·7 := 𝑛·1·6  # 𝕄(𝑛·1·5)"                        ]        it "writes what is known about every symbol a 'symbolize' line minted" $@@ -1658,13 +1692,13 @@               testCLISucceeded ["morph", "--symbolic=" ++ stands, "--locator=Q.y", "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []           records <- readProtocol path           lines records-            `shouldBe` [ "𝕄(Φ.y)"-                       , "  𝔼(L_stand)  # 𝕄(Φ.y)"-                       , "    𝑛1.1 := 01-:Δ  # 𝕄(ξ.x)"+            `shouldBe` [ "𝕄(Φ.y):"+                       , "  𝔼(L_stand):"+                       , "    𝑛1·1 := 01-:Δ  # 𝕄(ξ.x)"                        , "    𝔻(𝜎1:λ) == 01-"-                       , "    𝑛2.1 := 𝜎1:λ  # 𝑛1"-                       , "    𝑛.1.1 := 𝜎1:λ:z  # 𝑛"-                       , "    𝑛.1.2 := 𝜎1:λ:z  # 𝕄(𝑛.1.1)"+                       , "    𝑛2·1 := 𝜎1:λ  # 𝑛1"+                       , "    𝑛·1·1 := 𝜎1:λ:z  # 𝑛"+                       , "    𝑛·1·2 := 𝜎1:λ:z  # 𝕄(𝑛·1·1)"                        ]        it "writes a deferred copy as a call of the object of the world it was made of" $@@ -1673,7 +1707,7 @@           withStdin "⟦ box(x) ↦ ⟦ φ ↦ x.next ⟧, y ↦ Φ.box( x ↦ ⟦ λ ⤍ 𝜎1 ⟧ ) ⟧" $             testCLISucceeded ["morph", "--deep", "--locator=Q.y", "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []           records <- readProtocol path-          lines records `shouldContain` ["  deferred(𝜎2) := Φ.box( x ↦ 𝜎1:λ )  # 𝕄(Φ.y)"]+          lines records `shouldContain` ["  deferred(𝜎2) := Φ.box( x ↦ 𝜎1:λ )"]        it "writes a deferred copy as it stands when the world declares no object it was made of" $         withTempFile "protocolXXXXXX.txt" $ \(path, stream) -> do@@ -1681,7 +1715,7 @@           withStdin "⟦ wrap(v) ↦ ⟦⟧, y ↦ Φ.wrap( v ↦ ⟦ b(x) ↦ ⟦ φ ↦ x.next ⟧ ⟧ ).v.b( x ↦ ⟦ λ ⤍ 𝜎1 ⟧ ) ⟧" $             testCLISucceeded ["morph", "--deep", "--locator=Q.y", "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []           records <- readProtocol path-          lines records `shouldContain` ["  applied(𝑛.0.2) := ⟦ x ↦ ∅, φ ↦ x.next ⟧( x ↦ 𝜎1:λ )  # 𝕄(Φ.y)", "  deferred(𝜎2) := 𝑛.0.2  # 𝕄(Φ.y)"]+          lines records `shouldContain` ["  𝑛·0·2 := ⟦ x ↦ ∅, φ ↦ x.next ⟧( x ↦ 𝜎1:λ )", "  deferred(𝜎2) := 𝑛·0·2"]        it "writes the symbol a cut answers a copy with" $         withTempFile "protocolXXXXXX.txt" $ \(path, stream) -> do@@ -1690,7 +1724,7 @@             withStdin "⟦ box(n) ↦ ⟦ φ ↦ Φ.loop( x ↦ Φ.box( n ↦ ξ.n ) ) ⟧, loop(x) ↦ L_loop:λ, y ↦ Φ.loop( x ↦ Φ.box( n ↦ ⟦ Δ ⤍ 01- ⟧ ) ) ⟧" $               testCLISucceeded ["morph", "--symbolic=" ++ loops, "--deep", "--acyclic=proven", "--locator=Q.y", "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []           records <- readProtocol path-          lines records `shouldContain` ["    applied(𝑛.1.3) := Φ.loop( x ↦ 𝑛.1.2 )  # 𝕄(Φ.a🌵0.φ)", "    looped(𝑛.1.3) := 𝜎1  # 𝕄(Φ.a🌵0.φ), proven"]+          lines records `shouldContain` ["        𝑛·1·3 := Φ.loop( x ↦ 𝑛·1·2 )", "        looped(𝑛·1·3) := 𝜎1  # proven"]        it "writes a told stall to the XML protocol" $         withTempFile "protocolXXXXXX.xml" $ \(path, stream) -> do@@ -1699,7 +1733,7 @@             withStdin "⟦ x ↦ ⟦ arg ↦ ⟦ λ ⤍ L_none ⟧, λ ⤍ L_outer ⟧, y ↦ ⟦ arg ↦ ⟦ λ ⤍ L_none ⟧, λ ⤍ L_outer ⟧ ⟧" $               testCLISucceeded ["morph", "--symbolic=" ++ outer, "--deep", "--partial", "--acyclic=plausible", "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []           records <- readProtocol path-          lines records `shouldContain` ["    <stall λ=\"L_none\"/>"]+          lines records `shouldContain` ["      <stall λ=\"L_none\"/>"]        it "writes a stuck firing to the XML protocol" $         withTempFile "protocolXXXXXX.xml" $ \(path, stream) -> do@@ -1708,7 +1742,7 @@             withStdin "⟦ x ↦ ⟦ arg ↦ ⟦ λ ⤍ L_absent ⟧, λ ⤍ L_outer ⟧ ⟧" $               testCLISucceeded ["morph", "--symbolic=" ++ outer, "--deep", "--partial", "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []           records <- readProtocol path-          lines records `shouldContain` ["    <unfinished λ=\"L_absent\"/>"]+          lines records `shouldContain` ["      <unfinished λ=\"L_absent\"/>"]        it "writes a starved step budget to the XML protocol" $         withTempFile "protocolXXXXXX.xml" $ \(path, stream) -> do@@ -1717,10 +1751,10 @@             withStdin "⟦ x ↦ ⟦ arg ↦ ⟦ φ ↦ ⟦ φ ↦ ⟦ Δ ⤍ 07- ⟧ ⟧ ⟧, λ ⤍ L_outer ⟧ ⟧" $               testCLISucceeded ["dataize", "--symbolic=" ++ outer, "--locator=Q.x", "--partial", "--max-steps=3", "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho", "--flat"] []           records <- readProtocol path-          lines records `shouldContain` ["        <starved limit=\"3\" by=\"dataize\" at=\"Φ.a🌵0\"/>"]+          lines records `shouldContain` ["      <starved limit=\"3\" by=\"dataize\" at=\"Φ.a🌵0\"/>"]        forM_-        [("XMLXXXXXX.xml", "<spent limit=\"5\" by="), ("textXXXXXX.txt", "spent(5)  # ")]+        [("XMLXXXXXX.xml", "<spent limit=\"5\" by="), ("textXXXXXX.txt", "  spent(5)")]         ( \(template, record) ->             it ("writes a spent firing budget to the protocol as " ++ record) $               withTempFile template $ \(path, stream) -> do@@ -1741,25 +1775,28 @@               ["No entry of --symbolic answers the λ function 'L_number_nope'"]           records <- readProtocol path           lines records-            `shouldBe` [ "𝔻(Φ)"-                       , "  formation(⟦ bytes(φ) ↦ ⟦⟧, number(φ) ↦ ⟦ plus(x) ↦ L_number_plus:λ, nope ↦ L_number_nope:λ ⟧, φ ↦ 5.plus( 6 ).nope ⟧)  # 𝔻(Φ)"-                       , "    applied(𝑛.0.1) := 5  # 𝕄(Φ)"-                       , "    applied(𝑛.0.2) := 𝑛.0.1.plus( x ↦ 6 )  # 𝕄(Φ)"-                       , "    𝔼(L_number_plus)  # 𝕄(Φ)"-                       , "      applied(𝑛.1.1) := 5  # 𝕄(Φ.a🌵0)"-                       , "      formation(𝑛.1.1)  # 𝔻(Φ.a🌵0)"-                       , "        applied(𝑛.1.2) := Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵0)"-                       , "        formation(𝑛.1.2)  # 𝔻(Φ.a🌵0)"-                       , "      𝛿1.1 := 40-14-00-00-00-00-00-00  # 𝔻(ξ.ρ)"-                       , "      applied(𝑛.1.3) := 6  # 𝕄(Φ.a🌵1)"-                       , "      formation(𝑛.1.3)  # 𝔻(Φ.a🌵1)"-                       , "        applied(𝑛.1.4) := Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵1)"-                       , "        formation(𝑛.1.4)  # 𝔻(Φ.a🌵1)"-                       , "      𝛿2.1 := 40-18-00-00-00-00-00-00  # 𝔻(ξ.x)"-                       , "      𝑛.1.5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛"-                       , "      applied(𝑛.1.6) := Φ.number( φ ↦ 𝜎1:λ )  # 𝕄(Φ)"-                       , "      𝑛.1.7 := 𝑛.1.6  # 𝕄(𝑛.1.5)"-                       , "    unanswered(L_number_nope)  # 𝔻(L_number_nope:λ)"+            `shouldBe` [ "𝔻(Φ):"+                       , "  𝕄(Φ):"+                       , "    𝑛·0·1 := 5"+                       , "    𝑛·0·2 := 𝑛·0·1.plus( x ↦ 6 )"+                       , "    𝔼(L_number_plus):"+                       , "      𝔻(Φ.a🌵0):"+                       , "        𝕄(Φ.a🌵0):"+                       , "          𝑛·1·1 := 5"+                       , "          𝑛·1·2 := Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )"+                       , "        𝛿·1·1 := 40-14-00-00-00-00-00-00  # 5.0"+                       , "      𝛿1·1 := 𝛿·1·1  # 𝔻(ξ.ρ)"+                       , "      𝔻(Φ.a🌵1):"+                       , "        𝕄(Φ.a🌵1):"+                       , "          𝑛·1·3 := 6"+                       , "          𝑛·1·4 := Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )"+                       , "        𝛿·1·2 := 40-18-00-00-00-00-00-00  # 6.0"+                       , "      𝛿2·1 := 𝛿·1·2  # 𝔻(ξ.x)"+                       , "      𝑛·1·5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛"+                       , "      𝕄(𝑛·1·5):"+                       , "        𝑛·1·6 := Φ.number( φ ↦ 𝜎1:λ )"+                       , "      𝑛·1·7 := 𝑛·1·6  # 𝕄(𝑛·1·5)"+                       , "  unanswered(L_number_nope)  # 𝔻(L_number_nope:λ)"                        ]        it "truncates the lines left over from the previous run" $@@ -1767,7 +1804,7 @@           withStdin "[[ D> 01- ]]" $             testCLISucceeded ["dataize", "--protocol=" ++ path, "--quiet"] []           records <- readProtocol path-          records `shouldBe` "𝔻(Φ)\n"+          records `shouldBe` "𝔻(Φ):\n  𝛿·0·1 := 01-\n"        it "writes the lines in 𝜑 even with --output=xmir" $         withTempFile "protocolXXXXXX.txt" $ \(path, stream) -> do@@ -1775,7 +1812,7 @@           withStdin sum' $             testCLISucceeded ["dataize", symbolic, "--protocol=" ++ path, "--output=xmir", "--quiet", "--sweet", "--hide-rho"] []           records <- readProtocol path-          records `shouldEndWith` "      applied(𝑛.1.6) := Φ.number( φ ↦ 𝜎1:λ )  # 𝕄(Φ)\n      𝑛.1.7 := 𝑛.1.6  # 𝕄(𝑛.1.5)\n    formation(𝑛.1.6)  # 𝔻(Φ)\n"+          records `shouldEndWith` "    𝕄(𝑛·1·5):\n      𝑛·1·6 := Φ.number( φ ↦ 𝜎1:λ )\n    𝑛·1·7 := 𝑛·1·6  # 𝕄(𝑛·1·5)\n"        describe "as XML" $ do         it "writes the document when the file is named .xml" $@@ -1787,32 +1824,34 @@             lines records               `shouldBe` [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"                          , "<dataize at=\"Φ\">"-                         , "  <formation at=\"Φ\" term=\"⟦ bytes(φ) ↦ ⟦⟧, number(φ) ↦ ⟦ plus(x) ↦ L_number_plus:λ ⟧, φ ↦ 5.plus( 6 ) ⟧\">"-                         , "    <applied meta=\"𝑛.0.1\" by=\"morph\" at=\"Φ\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>"-                         , "    <applied meta=\"𝑛.0.2\" by=\"morph\" at=\"Φ\" of=\"𝑛.0.1.plus\"><attr name=\"x\">6</attr></applied>"-                         , "    <evaluate λ=\"L_number_plus\" by=\"dataize\" at=\"Φ\">"-                         , "      <applied meta=\"𝑛.1.1\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>"-                         , "      <formation at=\"Φ.a🌵0\" term=\"𝑛.1.1\">"-                         , "        <applied meta=\"𝑛.1.2\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.bytes\"><attr name=\"φ\">40-14-00-00-00-00-00-00:Δ</attr></applied>"-                         , "        <formation at=\"Φ.a🌵0\" term=\"𝑛.1.2\">"-                         , "        </formation>"-                         , "      </formation>"-                         , "      <bind meta=\"𝛿1.1\">40-14-00-00-00-00-00-00</bind>"-                         , "      <applied meta=\"𝑛.1.3\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )</attr></applied>"-                         , "      <formation at=\"Φ.a🌵1\" term=\"𝑛.1.3\">"-                         , "        <applied meta=\"𝑛.1.4\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.bytes\"><attr name=\"φ\">40-18-00-00-00-00-00-00:Δ</attr></applied>"-                         , "        <formation at=\"Φ.a🌵1\" term=\"𝑛.1.4\">"-                         , "        </formation>"-                         , "      </formation>"-                         , "      <bind meta=\"𝛿2.1\">40-18-00-00-00-00-00-00</bind>"-                         , "      <minted symbol=\"𝜎1\">40-14-00-00-00-00-00-00 40-18-00-00-00-00-00-00</minted>"-                         , "      <built meta=\"𝑛.1.5\">Φ.number( φ ↦ 𝜎1:λ )</built>"-                         , "      <applied meta=\"𝑛.1.6\" by=\"morph\" at=\"Φ\" of=\"Φ.number\"><attr name=\"φ\">𝜎1</attr></applied>"-                         , "      <answer meta=\"𝑛.1.7\">𝑛.1.6</answer>"-                         , "    </evaluate>"-                         , "    <formation at=\"Φ\" term=\"𝑛.1.6\">"-                         , "    </formation>"-                         , "  </formation>"+                         , "  <morph at=\"Φ\">"+                         , "    <applied meta=\"𝑛·0·1\" by=\"morph\" at=\"Φ\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>"+                         , "    <applied meta=\"𝑛·0·2\" by=\"morph\" at=\"Φ\" of=\"𝑛·0·1.plus\"><attr name=\"x\">6</attr></applied>"+                         , "  </morph>"+                         , "  <evaluate λ=\"L_number_plus\" by=\"dataize\" at=\"Φ\">"+                         , "    <dataize at=\"Φ.a🌵0\">"+                         , "      <morph at=\"Φ.a🌵0\">"+                         , "        <applied meta=\"𝑛·1·1\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>"+                         , "        <applied meta=\"𝑛·1·2\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.bytes\"><attr name=\"φ\">40-14-00-00-00-00-00-00:Δ</attr></applied>"+                         , "      </morph>"+                         , "      <delta meta=\"𝛿·1·1\" number=\"5.0\">40-14-00-00-00-00-00-00</delta>"+                         , "    </dataize>"+                         , "    <bind meta=\"𝛿1·1\">𝛿·1·1</bind>"+                         , "    <dataize at=\"Φ.a🌵1\">"+                         , "      <morph at=\"Φ.a🌵1\">"+                         , "        <applied meta=\"𝑛·1·3\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )</attr></applied>"+                         , "        <applied meta=\"𝑛·1·4\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.bytes\"><attr name=\"φ\">40-18-00-00-00-00-00-00:Δ</attr></applied>"+                         , "      </morph>"+                         , "      <delta meta=\"𝛿·1·2\" number=\"6.0\">40-18-00-00-00-00-00-00</delta>"+                         , "    </dataize>"+                         , "    <bind meta=\"𝛿2·1\">𝛿·1·2</bind>"+                         , "    <minted symbol=\"𝜎1\">40-14-00-00-00-00-00-00 40-18-00-00-00-00-00-00</minted>"+                         , "    <built meta=\"𝑛·1·5\">Φ.number( φ ↦ 𝜎1:λ )</built>"+                         , "    <morph at=\"𝑛·1·5\">"+                         , "      <applied meta=\"𝑛·1·6\" by=\"morph\" at=\"𝑛·1·5\" of=\"Φ.number\"><attr name=\"φ\">𝜎1</attr></applied>"+                         , "    </morph>"+                         , "    <answer meta=\"𝑛·1·7\">𝑛·1·6</answer>"+                         , "  </evaluate>"                          , "</dataize>"                          ] @@ -1826,7 +1865,7 @@               `shouldBe` [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"                          , "<protocol>"                          , "  <dataize at=\"Φ\">"-                         , "  </dataize>"+                         , "    <delta meta=\"𝛿·0·1\">01-</delta>"                          ]          it "closes the '<protocol>' root with its msec" $@@ -1835,7 +1874,7 @@             withStdin "[[ D> 01- ]]" $               testCLISucceeded ["dataize", "--protocol=" ++ path, "--quiet"] []             records <- readUtf8 path-            (lines records !! 4) `shouldSatisfy` isPrefixOf "  <msec>"+            (lines records !! 5) `shouldSatisfy` isPrefixOf "  <msec>"          it "closes the '<protocol>' root with its firings" $           withTempFile "protocolXXXXXX.xml" $ \(path, stream) -> do@@ -1851,17 +1890,18 @@             withStdin "[[ D> 01- ]]" $               testCLISucceeded ["dataize", "--protocol=" ++ path, "--quiet"] []             records <- readUtf8 path-            drop 6 (lines records) `shouldBe` ["  <fps>0</fps>", "</protocol>"]+            drop 7 (lines records) `shouldBe` ["  <fps>0</fps>", "</protocol>"] -        it "nests what a φ body fires inside the formation element it was boxed from" $+        it "nests what a φ body dataizes inside the element of the box rule that entered it" $           withTempFile "protocolXXXXXX.xml" $ \(path, stream) -> do             hClose stream             withStdin sum' $               testCLISucceeded ["dataize", symbolic, "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []             records <- readProtocol path-            filter (not . isInfixOf "<applied ") (lines records)-              `shouldContain` [ "  <formation at=\"Φ\" term=\"⟦ bytes(φ) ↦ ⟦⟧, number(φ) ↦ ⟦ plus(x) ↦ L_number_plus:λ ⟧, φ ↦ 5.plus( 6 ) ⟧\">"-                              , "    <evaluate λ=\"L_number_plus\" by=\"dataize\" at=\"Φ\">"+            filter (\line -> not (any (`isInfixOf` line) ["<applied ", "<morph ", "</morph>"])) (lines records)+              `shouldContain` [ "    <dataize at=\"Φ.a🌵0\">"+                              , "      <delta meta=\"𝛿·1·1\" number=\"5.0\">40-14-00-00-00-00-00-00</delta>"+                              , "    </dataize>"                               ]          it "closes the document even when nothing fires" $@@ -1873,6 +1913,7 @@             lines records               `shouldBe` [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"                          , "<dataize at=\"Φ\">"+                         , "  <delta meta=\"𝛿·0·1\">01-</delta>"                          , "</dataize>"                          ] @@ -1885,50 +1926,57 @@             lines records               `shouldBe` [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"                          , "<dataize at=\"Φ\">"-                         , "  <formation at=\"Φ\" term=\"⟦ bytes(φ) ↦ ⟦⟧, number(φ) ↦ ⟦ plus(x) ↦ L_number_plus:λ ⟧, φ ↦ 5.plus( 6 ).plus( 7 ) ⟧\">"-                         , "    <applied meta=\"𝑛.0.1\" by=\"morph\" at=\"Φ\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>"-                         , "    <applied meta=\"𝑛.0.2\" by=\"morph\" at=\"Φ\" of=\"𝑛.0.1.plus\"><attr name=\"x\">6</attr></applied>"+                         , "  <morph at=\"Φ\">"+                         , "    <applied meta=\"𝑛·0·1\" by=\"morph\" at=\"Φ\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>"+                         , "    <applied meta=\"𝑛·0·2\" by=\"morph\" at=\"Φ\" of=\"𝑛·0·1.plus\"><attr name=\"x\">6</attr></applied>"                          , "    <evaluate λ=\"L_number_plus\" by=\"morph\" at=\"Φ\">"-                         , "      <applied meta=\"𝑛.1.1\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>"-                         , "      <formation at=\"Φ.a🌵0\" term=\"𝑛.1.1\">"-                         , "        <applied meta=\"𝑛.1.2\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.bytes\"><attr name=\"φ\">40-14-00-00-00-00-00-00:Δ</attr></applied>"-                         , "        <formation at=\"Φ.a🌵0\" term=\"𝑛.1.2\">"-                         , "        </formation>"-                         , "      </formation>"-                         , "      <bind meta=\"𝛿1.1\">40-14-00-00-00-00-00-00</bind>"-                         , "      <applied meta=\"𝑛.1.3\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )</attr></applied>"-                         , "      <formation at=\"Φ.a🌵1\" term=\"𝑛.1.3\">"-                         , "        <applied meta=\"𝑛.1.4\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.bytes\"><attr name=\"φ\">40-18-00-00-00-00-00-00:Δ</attr></applied>"-                         , "        <formation at=\"Φ.a🌵1\" term=\"𝑛.1.4\">"-                         , "        </formation>"-                         , "      </formation>"-                         , "      <bind meta=\"𝛿2.1\">40-18-00-00-00-00-00-00</bind>"+                         , "      <dataize at=\"Φ.a🌵0\">"+                         , "        <morph at=\"Φ.a🌵0\">"+                         , "          <applied meta=\"𝑛·1·1\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>"+                         , "          <applied meta=\"𝑛·1·2\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.bytes\"><attr name=\"φ\">40-14-00-00-00-00-00-00:Δ</attr></applied>"+                         , "        </morph>"+                         , "        <delta meta=\"𝛿·1·1\" number=\"5.0\">40-14-00-00-00-00-00-00</delta>"+                         , "      </dataize>"+                         , "      <bind meta=\"𝛿1·1\">𝛿·1·1</bind>"+                         , "      <dataize at=\"Φ.a🌵1\">"+                         , "        <morph at=\"Φ.a🌵1\">"+                         , "          <applied meta=\"𝑛·1·3\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )</attr></applied>"+                         , "          <applied meta=\"𝑛·1·4\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.bytes\"><attr name=\"φ\">40-18-00-00-00-00-00-00:Δ</attr></applied>"+                         , "        </morph>"+                         , "        <delta meta=\"𝛿·1·2\" number=\"6.0\">40-18-00-00-00-00-00-00</delta>"+                         , "      </dataize>"+                         , "      <bind meta=\"𝛿2·1\">𝛿·1·2</bind>"                          , "      <minted symbol=\"𝜎1\">40-14-00-00-00-00-00-00 40-18-00-00-00-00-00-00</minted>"-                         , "      <built meta=\"𝑛.1.5\">Φ.number( φ ↦ 𝜎1:λ )</built>"-                         , "      <applied meta=\"𝑛.1.6\" by=\"morph\" at=\"Φ\" of=\"Φ.number\"><attr name=\"φ\">𝜎1</attr></applied>"-                         , "      <answer meta=\"𝑛.1.7\">𝑛.1.6</answer>"-                         , "    </evaluate>"-                         , "    <applied meta=\"𝑛.0.3\" by=\"morph\" at=\"Φ\" of=\"𝑛.1.6.plus\"><attr name=\"x\">7</attr></applied>"-                         , "    <evaluate λ=\"L_number_plus\" by=\"dataize\" at=\"Φ\">"-                         , "      <applied meta=\"𝑛.2.1\" by=\"morph\" at=\"Φ.a🌵2\" of=\"Φ.number\"><attr name=\"φ\">𝜎1</attr></applied>"-                         , "      <formation at=\"Φ.a🌵2\" term=\"𝑛.2.1\">"-                         , "      </formation>"-                         , "      <dataize meta=\"𝛿1.2\">𝜎1:λ</dataize>"-                         , "      <applied meta=\"𝑛.2.2\" by=\"morph\" at=\"Φ.a🌵3\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-1C-00-00-00-00-00-00:Δ )</attr></applied>"-                         , "      <formation at=\"Φ.a🌵3\" term=\"𝑛.2.2\">"-                         , "        <applied meta=\"𝑛.2.3\" by=\"morph\" at=\"Φ.a🌵3\" of=\"Φ.bytes\"><attr name=\"φ\">40-1C-00-00-00-00-00-00:Δ</attr></applied>"-                         , "        <formation at=\"Φ.a🌵3\" term=\"𝑛.2.3\">"-                         , "        </formation>"-                         , "      </formation>"-                         , "      <bind meta=\"𝛿2.2\">40-1C-00-00-00-00-00-00</bind>"-                         , "      <minted symbol=\"𝜎2\">𝜎1 40-1C-00-00-00-00-00-00</minted>"-                         , "      <built meta=\"𝑛.2.4\">Φ.number( φ ↦ 𝜎2:λ )</built>"-                         , "      <applied meta=\"𝑛.2.5\" by=\"morph\" at=\"Φ\" of=\"Φ.number\"><attr name=\"φ\">𝜎2</attr></applied>"-                         , "      <answer meta=\"𝑛.2.6\">𝑛.2.5</answer>"+                         , "      <built meta=\"𝑛·1·5\">Φ.number( φ ↦ 𝜎1:λ )</built>"+                         , "      <morph at=\"𝑛·1·5\">"+                         , "        <applied meta=\"𝑛·1·6\" by=\"morph\" at=\"𝑛·1·5\" of=\"Φ.number\"><attr name=\"φ\">𝜎1</attr></applied>"+                         , "      </morph>"+                         , "      <answer meta=\"𝑛·1·7\">𝑛·1·6</answer>"                          , "    </evaluate>"-                         , "    <formation at=\"Φ\" term=\"𝑛.2.5\">"-                         , "    </formation>"-                         , "  </formation>"+                         , "    <applied meta=\"𝑛·0·3\" by=\"morph\" at=\"Φ\" of=\"𝑛·1·6.plus\"><attr name=\"x\">7</attr></applied>"+                         , "  </morph>"+                         , "  <evaluate λ=\"L_number_plus\" by=\"dataize\" at=\"Φ\">"+                         , "    <dataize at=\"Φ.a🌵2\">"+                         , "      <morph at=\"Φ.a🌵2\">"+                         , "        <applied meta=\"𝑛·2·1\" by=\"morph\" at=\"Φ.a🌵2\" of=\"Φ.number\"><attr name=\"φ\">𝜎1</attr></applied>"+                         , "      </morph>"+                         , "    </dataize>"+                         , "    <dataize meta=\"𝛿1·2\">𝜎1:λ</dataize>"+                         , "    <dataize at=\"Φ.a🌵3\">"+                         , "      <morph at=\"Φ.a🌵3\">"+                         , "        <applied meta=\"𝑛·2·2\" by=\"morph\" at=\"Φ.a🌵3\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-1C-00-00-00-00-00-00:Δ )</attr></applied>"+                         , "        <applied meta=\"𝑛·2·3\" by=\"morph\" at=\"Φ.a🌵3\" of=\"Φ.bytes\"><attr name=\"φ\">40-1C-00-00-00-00-00-00:Δ</attr></applied>"+                         , "      </morph>"+                         , "      <delta meta=\"𝛿·2·1\" number=\"7.0\">40-1C-00-00-00-00-00-00</delta>"+                         , "    </dataize>"+                         , "    <bind meta=\"𝛿2·2\">𝛿·2·1</bind>"+                         , "    <minted symbol=\"𝜎2\">𝜎1 40-1C-00-00-00-00-00-00</minted>"+                         , "    <built meta=\"𝑛·2·4\">Φ.number( φ ↦ 𝜎2:λ )</built>"+                         , "    <morph at=\"𝑛·2·4\">"+                         , "      <applied meta=\"𝑛·2·5\" by=\"morph\" at=\"𝑛·2·4\" of=\"Φ.number\"><attr name=\"φ\">𝜎2</attr></applied>"+                         , "    </morph>"+                         , "    <answer meta=\"𝑛·2·6\">𝑛·2·5</answer>"+                         , "  </evaluate>"                          , "</dataize>"                          ] @@ -1943,11 +1991,11 @@               `shouldBe` [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"                          , "<morph at=\"Φ.y\">"                          , "  <evaluate λ=\"L_stand\" by=\"morph\" at=\"Φ.y\">"-                         , "    <bind meta=\"𝑛1.1\">01-:Δ</bind>"+                         , "    <bind meta=\"𝑛1·1\">01-:Δ</bind>"                          , "    <known symbol=\"𝜎1\">01-</known>"-                         , "    <bind meta=\"𝑛2.1\">𝜎1:λ</bind>"-                         , "    <built meta=\"𝑛.1.1\">𝜎1:λ:z</built>"-                         , "    <answer meta=\"𝑛.1.2\">𝜎1:λ:z</answer>"+                         , "    <bind meta=\"𝑛2·1\">𝜎1:λ</bind>"+                         , "    <built meta=\"𝑛·1·1\">𝜎1:λ:z</built>"+                         , "    <answer meta=\"𝑛·1·2\">𝜎1:λ:z</answer>"                          , "  </evaluate>"                          , "</morph>"                          ]@@ -1963,12 +2011,12 @@               `shouldBe` [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"                          , "<morph at=\"Φ.y\">"                          , "  <evaluate λ=\"L_fork\" by=\"morph\" at=\"Φ.y\">"-                         , "    <bind meta=\"𝑛1.1\">𝜎1:λ:φ</bind>"-                         , "    <bind meta=\"𝑛2.1\">𝜎2:λ:φ</bind>"+                         , "    <bind meta=\"𝑛1·1\">𝜎1:λ:φ</bind>"+                         , "    <bind meta=\"𝑛2·1\">𝜎2:λ:φ</bind>"                          , "    <joined symbol=\"𝜎3\">𝜎1 𝜎2</joined>"-                         , "    <bind meta=\"𝑛3.1\">𝜎3:λ:φ</bind>"-                         , "    <built meta=\"𝑛.1.1\">𝜎3:λ:φ</built>"-                         , "    <answer meta=\"𝑛.1.2\">𝜎3:λ:φ</answer>"+                         , "    <bind meta=\"𝑛3·1\">𝜎3:λ:φ</bind>"+                         , "    <built meta=\"𝑛·1·1\">𝜎3:λ:φ</built>"+                         , "    <answer meta=\"𝑛·1·2\">𝜎3:λ:φ</answer>"                          , "  </evaluate>"                          , "</morph>"                          ]@@ -1984,13 +2032,13 @@               `shouldBe` [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"                          , "<morph at=\"Φ.y\">"                          , "  <evaluate λ=\"L_fork\" by=\"morph\" at=\"Φ.y\">"-                         , "    <dataize meta=\"𝛿1.1\">𝜎1:λ</dataize>"-                         , "    <bind meta=\"𝑛1.1\">𝜎2:λ:φ</bind>"-                         , "    <bind meta=\"𝑛2.1\">⊥</bind>"+                         , "    <dataize meta=\"𝛿1·1\">𝜎1:λ</dataize>"+                         , "    <bind meta=\"𝑛1·1\">𝜎2:λ:φ</bind>"+                         , "    <bind meta=\"𝑛2·1\">⊥</bind>"                          , "    <terminate symbol=\"𝜎1\" branch=\"right\"/>"-                         , "    <bind meta=\"𝑛3.1\">𝜎2:λ:φ</bind>"-                         , "    <built meta=\"𝑛.1.1\">𝜎2:λ:φ</built>"-                         , "    <answer meta=\"𝑛.1.2\">𝜎2:λ:φ</answer>"+                         , "    <bind meta=\"𝑛3·1\">𝜎2:λ:φ</bind>"+                         , "    <built meta=\"𝑛·1·1\">𝜎2:λ:φ</built>"+                         , "    <answer meta=\"𝑛·1·2\">𝜎2:λ:φ</answer>"                          , "  </evaluate>"                          , "</morph>"                          ]@@ -2006,11 +2054,11 @@               `shouldBe` [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"                          , "<morph at=\"Φ.y\">"                          , "  <evaluate λ=\"L_pair\" by=\"morph\" at=\"Φ.y\">"-                         , "    <bind meta=\"𝑛1.1\">01-:Δ</bind>"+                         , "    <bind meta=\"𝑛1·1\">01-:Δ</bind>"                          , "    <minted symbol=\"𝜎1\"/>"                          , "    <minted symbol=\"𝜎2\"/>"-                         , "    <built meta=\"𝑛.1.1\">⟦ left ↦ 𝜎1:λ, right ↦ 𝜎2:λ ⟧</built>"-                         , "    <answer meta=\"𝑛.1.2\">⟦ left ↦ 𝜎1:λ, right ↦ 𝜎2:λ ⟧</answer>"+                         , "    <built meta=\"𝑛·1·1\">⟦ left ↦ 𝜎1:λ, right ↦ 𝜎2:λ ⟧</built>"+                         , "    <answer meta=\"𝑛·1·2\">⟦ left ↦ 𝜎1:λ, right ↦ 𝜎2:λ ⟧</answer>"                          , "  </evaluate>"                          , "</morph>"                          ]@@ -2024,8 +2072,8 @@             lines records               `shouldBe` [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"                          , "<morph at=\"Φ.y\">"-                         , "  <applied meta=\"𝑛.0.1\" by=\"morph\" at=\"Φ.y\" of=\"Φ.box\"><attr name=\"x\">𝜎1</attr></applied>"-                         , "  <deferred symbol=\"𝜎2\" by=\"morph\" at=\"Φ.y\" of=\"Φ.box\"><with><attr name=\"x\">𝜎1</attr></with><e>𝑛.0.1</e></deferred>"+                         , "  <applied meta=\"𝑛·0·1\" by=\"morph\" at=\"Φ.y\" of=\"Φ.box\"><attr name=\"x\">𝜎1</attr></applied>"+                         , "  <deferred symbol=\"𝜎2\" by=\"morph\" at=\"Φ.y\" of=\"Φ.box\"><with><attr name=\"x\">𝜎1</attr></with><e>𝑛·0·1</e></deferred>"                          , "</morph>"                          ] @@ -2035,7 +2083,7 @@             withStdin "⟦ joined(items) ↦ ⟦ φ ↦ step( tup ↦ items ), step(ρ, tup) ↦ ⟦ φ ↦ tup.next ⟧ ⟧, y ↦ Φ.joined( items ↦ ⟦ λ ⤍ 𝜎1 ⟧ ).φ ⟧" $               testCLISucceeded ["morph", "--deep", "--locator=Q.y", "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []             records <- readProtocol path-            lines records `shouldContain` ["  <deferred symbol=\"𝜎2\" by=\"morph\" at=\"Φ.y\" of=\"Φ.joined.step\"><with><attr name=\"tup\">𝜎1</attr></with><e>𝑛.0.2</e></deferred>"]+            lines records `shouldContain` ["  <deferred symbol=\"𝜎2\" by=\"morph\" at=\"Φ.y\" of=\"Φ.joined.step\"><with><attr name=\"tup\">𝜎1</attr></with><e>𝑛·0·2</e></deferred>"]          it "names the object a deferred copy was made of after the walk wrote an answer into its ρ" $           withTempFile "protocolXXXXXX.xml" $ \(path, stream) -> do@@ -2044,7 +2092,7 @@               withStdin "⟦ bytes(φ) ↦ ⟦⟧, dataized(target) ↦ L_dataized:λ, joined(items) ↦ ⟦ φ ↦ step( tup ↦ items, s ↦ sep ), sep ↦ Φ.dataized( target ↦ items ), step(ρ, tup, s) ↦ ⟦ φ ↦ tup.next ⟧ ⟧, y ↦ Φ.joined( items ↦ ⟦ λ ⤍ 𝜎1 ⟧ ).φ ⟧" $                 testCLISucceeded ["morph", "--deep", "--symbolic=" ++ dataized, "--locator=Q.y", "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []             records <- readProtocol path-            lines records `shouldContain` ["  <deferred symbol=\"𝜎3\" by=\"morph\" at=\"Φ.y\" of=\"Φ.joined.step\"><with><attr name=\"tup\">𝜎1</attr><attr name=\"s\">𝜎2</attr></with><e>𝑛.0.4</e></deferred>"]+            lines records `shouldContain` ["  <deferred symbol=\"𝜎3\" by=\"morph\" at=\"Φ.y\" of=\"Φ.joined.step\"><with><attr name=\"tup\">𝜎1</attr><attr name=\"s\">𝜎2</attr></with><e>𝑛·0·4</e></deferred>"]          it "writes a question mark for an argument of a deferred copy that is no bare symbol" $           withTempFile "protocolXXXXXX.xml" $ \(path, stream) -> do@@ -2052,7 +2100,7 @@             withStdin "⟦ box(x, w) ↦ ⟦ φ ↦ x.next ⟧, y ↦ Φ.box( x ↦ ⟦ λ ⤍ 𝜎1 ⟧, w ↦ ⟦ z ↦ Φ ⟧ ) ⟧" $               testCLISucceeded ["morph", "--deep", "--locator=Q.y", "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []             records <- readProtocol path-            lines records `shouldContain` ["  <deferred symbol=\"𝜎2\" by=\"morph\" at=\"Φ.y\" of=\"Φ.box\"><with><attr name=\"x\">𝜎1</attr><attr name=\"w\">?</attr></with><e>𝑛.0.2</e></deferred>"]+            lines records `shouldContain` ["  <deferred symbol=\"𝜎2\" by=\"morph\" at=\"Φ.y\" of=\"Φ.box\"><with><attr name=\"x\">𝜎1</attr><attr name=\"w\">?</attr></with><e>𝑛·0·2</e></deferred>"]          it "writes the object a deferred copy was made of whatever --abridged says" $           withTempFile "protocolXXXXXX.xml" $ \(path, stream) -> do@@ -2060,7 +2108,7 @@             withStdin "⟦ joined(items) ↦ ⟦ φ ↦ step( tup ↦ items ), step(ρ, tup) ↦ ⟦ φ ↦ tup.next ⟧ ⟧, y ↦ Φ.joined( items ↦ ⟦ λ ⤍ 𝜎1 ⟧ ).φ ⟧" $               testCLISucceeded ["morph", "--deep", "--locator=Q.y", "--protocol=" ++ path, "--abridged=20", "--quiet", "--sweet", "--hide-rho"] []             records <- readProtocol path-            lines records `shouldContain` ["  <deferred symbol=\"𝜎2\" by=\"morph\" at=\"Φ.y\" of=\"Φ.joined.step\"><with><attr name=\"tup\">𝜎1</attr></with><e>𝑛.0.2</e></deferred>"]+            lines records `shouldContain` ["  <deferred symbol=\"𝜎2\" by=\"morph\" at=\"Φ.y\" of=\"Φ.joined.step\"><with><attr name=\"tup\">𝜎1</attr></with><e>𝑛·0·2</e></deferred>"]          it "writes no object for a deferred copy of a formation the world does not declare" $           withTempFile "protocolXXXXXX.xml" $ \(path, stream) -> do@@ -2068,7 +2116,7 @@             withStdin "⟦ wrap(v) ↦ ⟦⟧, y ↦ Φ.wrap( v ↦ ⟦ b(x) ↦ ⟦ φ ↦ x.next ⟧ ⟧ ).v.b( x ↦ ⟦ λ ⤍ 𝜎1 ⟧ ) ⟧" $               testCLISucceeded ["morph", "--deep", "--locator=Q.y", "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []             records <- readProtocol path-            lines records `shouldContain` ["  <applied meta=\"𝑛.0.2\" by=\"morph\" at=\"Φ.y\" of=\"⟦ x ↦ ∅, φ ↦ x.next ⟧\"><attr name=\"x\">𝜎1</attr></applied>", "  <deferred symbol=\"𝜎2\" by=\"morph\" at=\"Φ.y\"><e>𝑛.0.2</e></deferred>"]+            lines records `shouldContain` ["  <applied meta=\"𝑛·0·2\" by=\"morph\" at=\"Φ.y\" of=\"⟦ x ↦ ∅, φ ↦ x.next ⟧\"><attr name=\"x\">𝜎1</attr></applied>", "  <deferred symbol=\"𝜎2\" by=\"morph\" at=\"Φ.y\"><e>𝑛·0·2</e></deferred>"]          it "writes the copy a cut answers as a call of the object it was made of" $           withTempFile "protocolXXXXXX.xml" $ \(path, stream) -> do@@ -2077,7 +2125,7 @@               withStdin "⟦ num(φ) ↦ ⟦⟧, box(n) ↦ ⟦ φ ↦ Φ.loop( x ↦ Φ.box( n ↦ ξ.n ) ) ⟧, loop(x) ↦ L_loop:λ, y ↦ Φ.loop( x ↦ Φ.box( n ↦ Φ.num( φ ↦ ⟦ λ ⤍ 𝜎1 ⟧ ) ) ) ⟧" $                 testCLISucceeded ["morph", "--symbolic=" ++ loops, "--deep", "--acyclic=plausible", "--locator=Q.y", "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []             records <- readProtocol path-            lines records `shouldContain` ["    <looped symbol=\"𝜎2\" by=\"morph\" match=\"plausible\" at=\"Φ.a🌵0.φ\" of=\"Φ.box\"><with><attr name=\"n\">𝜎1</attr></with><e>𝑛.0.1</e></looped>"]+            lines records `shouldContain` ["        <looped symbol=\"𝜎2\" by=\"morph\" match=\"plausible\" at=\"Φ.a🌵0.φ\" of=\"Φ.box\"><with><attr name=\"n\">𝜎1</attr></with><e>𝑛·0·1</e></looped>"]          it "writes no 'minted' element for a firing minting nothing" $           withTempFile "protocolXXXXXX.xml" $ \(path, stream) -> do@@ -2090,9 +2138,9 @@               `shouldBe` [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"                          , "<morph at=\"Φ.y\">"                          , "  <evaluate λ=\"L_keep\" by=\"morph\" at=\"Φ.y\">"-                         , "    <bind meta=\"𝑛1.1\">01-:Δ</bind>"-                         , "    <built meta=\"𝑛.1.1\">01-:Δ:z</built>"-                         , "    <answer meta=\"𝑛.1.2\">01-:Δ:z</answer>"+                         , "    <bind meta=\"𝑛1·1\">01-:Δ</bind>"+                         , "    <built meta=\"𝑛·1·1\">01-:Δ:z</built>"+                         , "    <answer meta=\"𝑛·1·2\">01-:Δ:z</answer>"                          , "  </evaluate>"                          , "</morph>"                          ]@@ -2106,50 +2154,57 @@             lines records               `shouldBe` [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"                          , "<dataize at=\"Φ\">"-                         , "  <formation at=\"Φ\" term=\"⟦ bytes(φ) ↦ ⟦⟧, number(φ) ↦ ⟦ plus(x) ↦ L_number_plus:λ ⟧, φ ↦ 5.plus( 6.plus( 7 ) ) ⟧\">"-                         , "    <applied meta=\"𝑛.0.1\" by=\"morph\" at=\"Φ\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>"-                         , "    <applied meta=\"𝑛.0.2\" by=\"morph\" at=\"Φ\" of=\"𝑛.0.1.plus\"><attr name=\"x\">6.plus( 7 )</attr></applied>"-                         , "    <evaluate λ=\"L_number_plus\" by=\"dataize\" at=\"Φ\">"-                         , "      <applied meta=\"𝑛.1.1\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>"-                         , "      <formation at=\"Φ.a🌵0\" term=\"𝑛.1.1\">"-                         , "        <applied meta=\"𝑛.1.2\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.bytes\"><attr name=\"φ\">40-14-00-00-00-00-00-00:Δ</attr></applied>"-                         , "        <formation at=\"Φ.a🌵0\" term=\"𝑛.1.2\">"-                         , "        </formation>"-                         , "      </formation>"-                         , "      <bind meta=\"𝛿1.1\">40-14-00-00-00-00-00-00</bind>"-                         , "      <applied meta=\"𝑛.1.3\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )</attr></applied>"-                         , "      <applied meta=\"𝑛.1.4\" by=\"morph\" at=\"Φ.a🌵1\" of=\"𝑛.1.3.plus\"><attr name=\"x\">7</attr></applied>"+                         , "  <morph at=\"Φ\">"+                         , "    <applied meta=\"𝑛·0·1\" by=\"morph\" at=\"Φ\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>"+                         , "    <applied meta=\"𝑛·0·2\" by=\"morph\" at=\"Φ\" of=\"𝑛·0·1.plus\"><attr name=\"x\">6.plus( 7 )</attr></applied>"+                         , "  </morph>"+                         , "  <evaluate λ=\"L_number_plus\" by=\"dataize\" at=\"Φ\">"+                         , "    <dataize at=\"Φ.a🌵0\">"+                         , "      <morph at=\"Φ.a🌵0\">"+                         , "        <applied meta=\"𝑛·1·1\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )</attr></applied>"+                         , "        <applied meta=\"𝑛·1·2\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.bytes\"><attr name=\"φ\">40-14-00-00-00-00-00-00:Δ</attr></applied>"+                         , "      </morph>"+                         , "      <delta meta=\"𝛿·1·1\" number=\"5.0\">40-14-00-00-00-00-00-00</delta>"+                         , "    </dataize>"+                         , "    <bind meta=\"𝛿1·1\">𝛿·1·1</bind>"+                         , "    <dataize at=\"Φ.a🌵1\">"+                         , "      <morph at=\"Φ.a🌵1\">"+                         , "        <applied meta=\"𝑛·1·3\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )</attr></applied>"+                         , "        <applied meta=\"𝑛·1·4\" by=\"morph\" at=\"Φ.a🌵1\" of=\"𝑛·1·3.plus\"><attr name=\"x\">7</attr></applied>"+                         , "      </morph>"                          , "      <evaluate λ=\"L_number_plus\" by=\"dataize\" at=\"Φ.a🌵1\">"-                         , "        <applied meta=\"𝑛.2.1\" by=\"morph\" at=\"Φ.a🌵2\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )</attr></applied>"-                         , "        <formation at=\"Φ.a🌵2\" term=\"𝑛.2.1\">"-                         , "          <applied meta=\"𝑛.2.2\" by=\"morph\" at=\"Φ.a🌵2\" of=\"Φ.bytes\"><attr name=\"φ\">40-18-00-00-00-00-00-00:Δ</attr></applied>"-                         , "          <formation at=\"Φ.a🌵2\" term=\"𝑛.2.2\">"-                         , "          </formation>"-                         , "        </formation>"-                         , "        <bind meta=\"𝛿1.2\">40-18-00-00-00-00-00-00</bind>"-                         , "        <applied meta=\"𝑛.2.3\" by=\"morph\" at=\"Φ.a🌵3\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-1C-00-00-00-00-00-00:Δ )</attr></applied>"-                         , "        <formation at=\"Φ.a🌵3\" term=\"𝑛.2.3\">"-                         , "          <applied meta=\"𝑛.2.4\" by=\"morph\" at=\"Φ.a🌵3\" of=\"Φ.bytes\"><attr name=\"φ\">40-1C-00-00-00-00-00-00:Δ</attr></applied>"-                         , "          <formation at=\"Φ.a🌵3\" term=\"𝑛.2.4\">"-                         , "          </formation>"-                         , "        </formation>"-                         , "        <bind meta=\"𝛿2.2\">40-1C-00-00-00-00-00-00</bind>"+                         , "        <dataize at=\"Φ.a🌵2\">"+                         , "          <morph at=\"Φ.a🌵2\">"+                         , "            <applied meta=\"𝑛·2·1\" by=\"morph\" at=\"Φ.a🌵2\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )</attr></applied>"+                         , "            <applied meta=\"𝑛·2·2\" by=\"morph\" at=\"Φ.a🌵2\" of=\"Φ.bytes\"><attr name=\"φ\">40-18-00-00-00-00-00-00:Δ</attr></applied>"+                         , "          </morph>"+                         , "          <delta meta=\"𝛿·2·1\" number=\"6.0\">40-18-00-00-00-00-00-00</delta>"+                         , "        </dataize>"+                         , "        <bind meta=\"𝛿1·2\">𝛿·2·1</bind>"+                         , "        <dataize at=\"Φ.a🌵3\">"+                         , "          <morph at=\"Φ.a🌵3\">"+                         , "            <applied meta=\"𝑛·2·3\" by=\"morph\" at=\"Φ.a🌵3\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-1C-00-00-00-00-00-00:Δ )</attr></applied>"+                         , "            <applied meta=\"𝑛·2·4\" by=\"morph\" at=\"Φ.a🌵3\" of=\"Φ.bytes\"><attr name=\"φ\">40-1C-00-00-00-00-00-00:Δ</attr></applied>"+                         , "          </morph>"+                         , "          <delta meta=\"𝛿·2·2\" number=\"7.0\">40-1C-00-00-00-00-00-00</delta>"+                         , "        </dataize>"+                         , "        <bind meta=\"𝛿2·2\">𝛿·2·2</bind>"                          , "        <minted symbol=\"𝜎1\">40-18-00-00-00-00-00-00 40-1C-00-00-00-00-00-00</minted>"-                         , "        <built meta=\"𝑛.2.5\">Φ.number( φ ↦ 𝜎1:λ )</built>"-                         , "        <applied meta=\"𝑛.2.6\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.number\"><attr name=\"φ\">𝜎1</attr></applied>"-                         , "        <answer meta=\"𝑛.2.7\">𝑛.2.6</answer>"+                         , "        <built meta=\"𝑛·2·5\">Φ.number( φ ↦ 𝜎1:λ )</built>"+                         , "        <morph at=\"𝑛·2·5\">"+                         , "          <applied meta=\"𝑛·2·6\" by=\"morph\" at=\"𝑛·2·5\" of=\"Φ.number\"><attr name=\"φ\">𝜎1</attr></applied>"+                         , "        </morph>"+                         , "        <answer meta=\"𝑛·2·7\">𝑛·2·6</answer>"                          , "      </evaluate>"-                         , "      <formation at=\"Φ.a🌵1\" term=\"𝑛.2.6\">"-                         , "      </formation>"-                         , "      <dataize meta=\"𝛿2.1\">𝜎1:λ</dataize>"-                         , "      <minted symbol=\"𝜎2\">40-14-00-00-00-00-00-00 𝜎1</minted>"-                         , "      <built meta=\"𝑛.1.5\">Φ.number( φ ↦ 𝜎2:λ )</built>"-                         , "      <applied meta=\"𝑛.1.6\" by=\"morph\" at=\"Φ\" of=\"Φ.number\"><attr name=\"φ\">𝜎2</attr></applied>"-                         , "      <answer meta=\"𝑛.1.7\">𝑛.1.6</answer>"-                         , "    </evaluate>"-                         , "    <formation at=\"Φ\" term=\"𝑛.1.6\">"-                         , "    </formation>"-                         , "  </formation>"+                         , "    </dataize>"+                         , "    <dataize meta=\"𝛿2·1\">𝜎1:λ</dataize>"+                         , "    <minted symbol=\"𝜎2\">40-14-00-00-00-00-00-00 𝜎1</minted>"+                         , "    <built meta=\"𝑛·1·5\">Φ.number( φ ↦ 𝜎2:λ )</built>"+                         , "    <morph at=\"𝑛·1·5\">"+                         , "      <applied meta=\"𝑛·1·6\" by=\"morph\" at=\"𝑛·1·5\" of=\"Φ.number\"><attr name=\"φ\">𝜎2</attr></applied>"+                         , "    </morph>"+                         , "    <answer meta=\"𝑛·1·7\">𝑛·1·6</answer>"+                         , "  </evaluate>"                          , "</dataize>"                          ] @@ -2162,31 +2217,35 @@             lines records               `shouldBe` [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"                          , "<dataize at=\"Φ\">"-                         , "  <formation at=\"Φ\" term=\"⟦ bytes(φ) ↦ ⟦⟧, number(φ) ↦ ⟦ times(x) ↦ L_number_times:λ, nope ↦ L_number_nope:λ ⟧, φ ↦ 2.times( 3 ).nope ⟧\">"-                         , "    <applied meta=\"𝑛.0.1\" by=\"morph\" at=\"Φ\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-00-00-00-00-00-00-00:Δ )</attr></applied>"-                         , "    <applied meta=\"𝑛.0.2\" by=\"morph\" at=\"Φ\" of=\"𝑛.0.1.times\"><attr name=\"x\">3</attr></applied>"+                         , "  <morph at=\"Φ\">"+                         , "    <applied meta=\"𝑛·0·1\" by=\"morph\" at=\"Φ\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-00-00-00-00-00-00-00:Δ )</attr></applied>"+                         , "    <applied meta=\"𝑛·0·2\" by=\"morph\" at=\"Φ\" of=\"𝑛·0·1.times\"><attr name=\"x\">3</attr></applied>"                          , "    <evaluate λ=\"L_number_times\" by=\"morph\" at=\"Φ\">"-                         , "      <applied meta=\"𝑛.1.1\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-00-00-00-00-00-00-00:Δ )</attr></applied>"-                         , "      <formation at=\"Φ.a🌵0\" term=\"𝑛.1.1\">"-                         , "        <applied meta=\"𝑛.1.2\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.bytes\"><attr name=\"φ\">40-00-00-00-00-00-00-00:Δ</attr></applied>"-                         , "        <formation at=\"Φ.a🌵0\" term=\"𝑛.1.2\">"-                         , "        </formation>"-                         , "      </formation>"-                         , "      <bind meta=\"𝛿1.1\">40-00-00-00-00-00-00-00</bind>"-                         , "      <applied meta=\"𝑛.1.3\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-08-00-00-00-00-00-00:Δ )</attr></applied>"-                         , "      <formation at=\"Φ.a🌵1\" term=\"𝑛.1.3\">"-                         , "        <applied meta=\"𝑛.1.4\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.bytes\"><attr name=\"φ\">40-08-00-00-00-00-00-00:Δ</attr></applied>"-                         , "        <formation at=\"Φ.a🌵1\" term=\"𝑛.1.4\">"-                         , "        </formation>"-                         , "      </formation>"-                         , "      <bind meta=\"𝛿2.1\">40-08-00-00-00-00-00-00</bind>"+                         , "      <dataize at=\"Φ.a🌵0\">"+                         , "        <morph at=\"Φ.a🌵0\">"+                         , "          <applied meta=\"𝑛·1·1\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-00-00-00-00-00-00-00:Δ )</attr></applied>"+                         , "          <applied meta=\"𝑛·1·2\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.bytes\"><attr name=\"φ\">40-00-00-00-00-00-00-00:Δ</attr></applied>"+                         , "        </morph>"+                         , "        <delta meta=\"𝛿·1·1\" number=\"2.0\">40-00-00-00-00-00-00-00</delta>"+                         , "      </dataize>"+                         , "      <bind meta=\"𝛿1·1\">𝛿·1·1</bind>"+                         , "      <dataize at=\"Φ.a🌵1\">"+                         , "        <morph at=\"Φ.a🌵1\">"+                         , "          <applied meta=\"𝑛·1·3\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ 40-08-00-00-00-00-00-00:Δ )</attr></applied>"+                         , "          <applied meta=\"𝑛·1·4\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.bytes\"><attr name=\"φ\">40-08-00-00-00-00-00-00:Δ</attr></applied>"+                         , "        </morph>"+                         , "        <delta meta=\"𝛿·1·2\" number=\"3.0\">40-08-00-00-00-00-00-00</delta>"+                         , "      </dataize>"+                         , "      <bind meta=\"𝛿2·1\">𝛿·1·2</bind>"                          , "      <minted symbol=\"𝜎1\">40-00-00-00-00-00-00-00 40-08-00-00-00-00-00-00</minted>"-                         , "      <built meta=\"𝑛.1.5\">Φ.number( φ ↦ 𝜎1:λ )</built>"-                         , "      <applied meta=\"𝑛.1.6\" by=\"morph\" at=\"Φ\" of=\"Φ.number\"><attr name=\"φ\">𝜎1</attr></applied>"-                         , "      <answer meta=\"𝑛.1.7\">𝑛.1.6</answer>"+                         , "      <built meta=\"𝑛·1·5\">Φ.number( φ ↦ 𝜎1:λ )</built>"+                         , "      <morph at=\"𝑛·1·5\">"+                         , "        <applied meta=\"𝑛·1·6\" by=\"morph\" at=\"𝑛·1·5\" of=\"Φ.number\"><attr name=\"φ\">𝜎1</attr></applied>"+                         , "      </morph>"+                         , "      <answer meta=\"𝑛·1·7\">𝑛·1·6</answer>"                          , "    </evaluate>"-                         , "    <unanswered λ=\"L_number_nope\" by=\"dataize\">L_number_nope:λ</unanswered>"-                         , "  </formation>"+                         , "  </morph>"+                         , "  <unanswered λ=\"L_number_nope\" by=\"dataize\">L_number_nope:λ</unanswered>"                          , "</dataize>"                          ] @@ -2212,31 +2271,35 @@             lines records               `shouldBe` [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"                          , "<dataize at=\"Φ\">"-                         , "  <formation at=\"Φ\" term=\"⟦ bytes ↦ ⟦ φ ↦ ∅ ⟧, number ↦ ⟦ φ ↦ ∅, times ↦ ⟦ ρ ↦ ∅, x ↦ ∅, λ ⤍ L_number_times ⟧, nope ↦ ⟦ ρ ↦ ∅, λ ⤍ L_number_nope ⟧ ⟧, φ ↦ Φ.number( φ ↦ Φ.bytes( φ ↦ ⟦ Δ ⤍ 40-00-00-00-00-00-00-00 ⟧ ) ).times( α0 ↦ Φ.number( φ ↦ Φ.bytes( φ ↦ ⟦ Δ ⤍ 40-08-00-00-00-00-00-00 ⟧ ) ) ).nope ⟧\">"-                         , "    <applied meta=\"𝑛.0.1\" by=\"morph\" at=\"Φ\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ ⟦ Δ ⤍ 40-00-00-00-00-00-00-00 ⟧ )</attr></applied>"-                         , "    <applied meta=\"𝑛.0.2\" by=\"morph\" at=\"Φ\" of=\"𝑛.0.1.times\"><attr name=\"x\">Φ.number( φ ↦ Φ.bytes( φ ↦ ⟦ Δ ⤍ 40-08-00-00-00-00-00-00 ⟧ ) )</attr></applied>"+                         , "  <morph at=\"Φ\">"+                         , "    <applied meta=\"𝑛·0·1\" by=\"morph\" at=\"Φ\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ ⟦ Δ ⤍ 40-00-00-00-00-00-00-00 ⟧ )</attr></applied>"+                         , "    <applied meta=\"𝑛·0·2\" by=\"morph\" at=\"Φ\" of=\"𝑛·0·1.times\"><attr name=\"x\">Φ.number( φ ↦ Φ.bytes( φ ↦ ⟦ Δ ⤍ 40-08-00-00-00-00-00-00 ⟧ ) )</attr></applied>"                          , "    <evaluate λ=\"L_number_times\" by=\"morph\" at=\"Φ\">"-                         , "      <applied meta=\"𝑛.1.1\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ ⟦ Δ ⤍ 40-00-00-00-00-00-00-00 ⟧ )</attr></applied>"-                         , "      <formation at=\"Φ.a🌵0\" term=\"𝑛.1.1\">"-                         , "        <applied meta=\"𝑛.1.2\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.bytes\"><attr name=\"φ\">⟦ Δ ⤍ 40-00-00-00-00-00-00-00 ⟧</attr></applied>"-                         , "        <formation at=\"Φ.a🌵0\" term=\"𝑛.1.2\">"-                         , "        </formation>"-                         , "      </formation>"-                         , "      <bind meta=\"𝛿1.1\">40-00-00-00-00-00-00-00</bind>"-                         , "      <applied meta=\"𝑛.1.3\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ ⟦ Δ ⤍ 40-08-00-00-00-00-00-00 ⟧ )</attr></applied>"-                         , "      <formation at=\"Φ.a🌵1\" term=\"𝑛.1.3\">"-                         , "        <applied meta=\"𝑛.1.4\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.bytes\"><attr name=\"φ\">⟦ Δ ⤍ 40-08-00-00-00-00-00-00 ⟧</attr></applied>"-                         , "        <formation at=\"Φ.a🌵1\" term=\"𝑛.1.4\">"-                         , "        </formation>"-                         , "      </formation>"-                         , "      <bind meta=\"𝛿2.1\">40-08-00-00-00-00-00-00</bind>"+                         , "      <dataize at=\"Φ.a🌵0\">"+                         , "        <morph at=\"Φ.a🌵0\">"+                         , "          <applied meta=\"𝑛·1·1\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ ⟦ Δ ⤍ 40-00-00-00-00-00-00-00 ⟧ )</attr></applied>"+                         , "          <applied meta=\"𝑛·1·2\" by=\"morph\" at=\"Φ.a🌵0\" of=\"Φ.bytes\"><attr name=\"φ\">⟦ Δ ⤍ 40-00-00-00-00-00-00-00 ⟧</attr></applied>"+                         , "        </morph>"+                         , "        <delta meta=\"𝛿·1·1\" number=\"2.0\">40-00-00-00-00-00-00-00</delta>"+                         , "      </dataize>"+                         , "      <bind meta=\"𝛿1·1\">𝛿·1·1</bind>"+                         , "      <dataize at=\"Φ.a🌵1\">"+                         , "        <morph at=\"Φ.a🌵1\">"+                         , "          <applied meta=\"𝑛·1·3\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.number\"><attr name=\"φ\">Φ.bytes( φ ↦ ⟦ Δ ⤍ 40-08-00-00-00-00-00-00 ⟧ )</attr></applied>"+                         , "          <applied meta=\"𝑛·1·4\" by=\"morph\" at=\"Φ.a🌵1\" of=\"Φ.bytes\"><attr name=\"φ\">⟦ Δ ⤍ 40-08-00-00-00-00-00-00 ⟧</attr></applied>"+                         , "        </morph>"+                         , "        <delta meta=\"𝛿·1·2\" number=\"3.0\">40-08-00-00-00-00-00-00</delta>"+                         , "      </dataize>"+                         , "      <bind meta=\"𝛿2·1\">𝛿·1·2</bind>"                          , "      <minted symbol=\"𝜎1\">40-00-00-00-00-00-00-00 40-08-00-00-00-00-00-00</minted>"-                         , "      <built meta=\"𝑛.1.5\">Φ.number( φ ↦ ⟦ λ ⤍ 𝜎1 ⟧ )</built>"-                         , "      <applied meta=\"𝑛.1.6\" by=\"morph\" at=\"Φ\" of=\"Φ.number\"><attr name=\"φ\">𝜎1</attr></applied>"-                         , "      <answer meta=\"𝑛.1.7\">𝑛.1.6</answer>"+                         , "      <built meta=\"𝑛·1·5\">Φ.number( φ ↦ ⟦ λ ⤍ 𝜎1 ⟧ )</built>"+                         , "      <morph at=\"𝑛·1·5\">"+                         , "        <applied meta=\"𝑛·1·6\" by=\"morph\" at=\"𝑛·1·5\" of=\"Φ.number\"><attr name=\"φ\">𝜎1</attr></applied>"+                         , "      </morph>"+                         , "      <answer meta=\"𝑛·1·7\">𝑛·1·6</answer>"                          , "    </evaluate>"-                         , "    <unanswered λ=\"L_number_nope\" by=\"dataize\">⟦ ρ ↦ 𝑛.1.6, λ ⤍ L_number_nope ⟧</unanswered>"-                         , "  </formation>"+                         , "  </morph>"+                         , "  <unanswered λ=\"L_number_nope\" by=\"dataize\">⟦ ρ ↦ 𝑛·1·6, λ ⤍ L_number_nope ⟧</unanswered>"                          , "</dataize>"                          ] @@ -2251,10 +2314,10 @@               `shouldBe` [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"                          , "<morph at=\"Φ.x\">"                          , "  <evaluate λ=\"L_pick\" by=\"morph\" at=\"Φ.x\">"-                         , "    <bind meta=\"𝑛1.1\">⊥</bind>"+                         , "    <bind meta=\"𝑛1·1\">⊥</bind>"                          , "    <minted symbol=\"𝜎1\"/>"-                         , "    <built meta=\"𝑛.1.1\">⟦ λ ⤍ 𝜎1 ⟧</built>"-                         , "    <answer meta=\"𝑛.1.2\">⟦ λ ⤍ 𝜎1 ⟧</answer>"+                         , "    <built meta=\"𝑛·1·1\">⟦ λ ⤍ 𝜎1 ⟧</built>"+                         , "    <answer meta=\"𝑛·1·2\">⟦ λ ⤍ 𝜎1 ⟧</answer>"                          , "  </evaluate>"                          , "  <unanswered λ=\"𝜎1\" by=\"morph\">⟦ λ ⤍ 𝜎1 ⟧</unanswered>"                          , "</morph>"@@ -2266,7 +2329,7 @@             withStdin sum' $               testCLISucceeded ["dataize", symbolic, "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []             records <- readProtocol path-            take 1 (lines records) `shouldBe` ["𝔻(Φ)"]+            take 1 (lines records) `shouldBe` ["𝔻(Φ):"]      describe "--partial" $ do       let stuck = "[[ bytes ↦ ⟦ φ ↦ ∅ ⟧, number(φ) -> [[ times(^, x) -> [[ L> L_number_times ]], nope -> [[ ^ -> ?, L> L_number_nope ]] ]], @ -> 2.times(3).nope ]]"@@ -2297,25 +2360,28 @@             testCLISucceeded ["dataize", symbolic, "--partial", "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []           records <- readProtocol path           lines records-            `shouldBe` [ "𝔻(Φ)"-                       , "  formation(⟦ bytes(φ) ↦ ⟦⟧, number(φ) ↦ ⟦ times(x) ↦ L_number_times:λ, nope ↦ L_number_nope:λ ⟧, φ ↦ 2.times( 3 ).nope ⟧)  # 𝔻(Φ)"-                       , "    applied(𝑛.0.1) := 2  # 𝕄(Φ)"-                       , "    applied(𝑛.0.2) := 𝑛.0.1.times( x ↦ 3 )  # 𝕄(Φ)"-                       , "    𝔼(L_number_times)  # 𝕄(Φ)"-                       , "      applied(𝑛.1.1) := 2  # 𝕄(Φ.a🌵0)"-                       , "      formation(𝑛.1.1)  # 𝔻(Φ.a🌵0)"-                       , "        applied(𝑛.1.2) := Φ.bytes( φ ↦ 40-00-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵0)"-                       , "        formation(𝑛.1.2)  # 𝔻(Φ.a🌵0)"-                       , "      𝛿1.1 := 40-00-00-00-00-00-00-00  # 𝔻(ξ.ρ)"-                       , "      applied(𝑛.1.3) := 3  # 𝕄(Φ.a🌵1)"-                       , "      formation(𝑛.1.3)  # 𝔻(Φ.a🌵1)"-                       , "        applied(𝑛.1.4) := Φ.bytes( φ ↦ 40-08-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵1)"-                       , "        formation(𝑛.1.4)  # 𝔻(Φ.a🌵1)"-                       , "      𝛿2.1 := 40-08-00-00-00-00-00-00  # 𝔻(ξ.x)"-                       , "      𝑛.1.5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛"-                       , "      applied(𝑛.1.6) := Φ.number( φ ↦ 𝜎1:λ )  # 𝕄(Φ)"-                       , "      𝑛.1.7 := 𝑛.1.6  # 𝕄(𝑛.1.5)"-                       , "    unanswered(L_number_nope)  # 𝔻(L_number_nope:λ)"+            `shouldBe` [ "𝔻(Φ):"+                       , "  𝕄(Φ):"+                       , "    𝑛·0·1 := 2"+                       , "    𝑛·0·2 := 𝑛·0·1.times( x ↦ 3 )"+                       , "    𝔼(L_number_times):"+                       , "      𝔻(Φ.a🌵0):"+                       , "        𝕄(Φ.a🌵0):"+                       , "          𝑛·1·1 := 2"+                       , "          𝑛·1·2 := Φ.bytes( φ ↦ 40-00-00-00-00-00-00-00:Δ )"+                       , "        𝛿·1·1 := 40-00-00-00-00-00-00-00  # 2.0"+                       , "      𝛿1·1 := 𝛿·1·1  # 𝔻(ξ.ρ)"+                       , "      𝔻(Φ.a🌵1):"+                       , "        𝕄(Φ.a🌵1):"+                       , "          𝑛·1·3 := 3"+                       , "          𝑛·1·4 := Φ.bytes( φ ↦ 40-08-00-00-00-00-00-00:Δ )"+                       , "        𝛿·1·2 := 40-08-00-00-00-00-00-00  # 3.0"+                       , "      𝛿2·1 := 𝛿·1·2  # 𝔻(ξ.x)"+                       , "      𝑛·1·5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛"+                       , "      𝕄(𝑛·1·5):"+                       , "        𝑛·1·6 := Φ.number( φ ↦ 𝜎1:λ )"+                       , "      𝑛·1·7 := 𝑛·1·6  # 𝕄(𝑛·1·5)"+                       , "  unanswered(L_number_nope)  # 𝔻(L_number_nope:λ)"                        ]        it "still prints bytes when nothing gets stuck" $@@ -2357,7 +2423,7 @@        it "reports the progress of the run with --log-level=INFO" $         withStdin sum' $-          testCLISucceeded ["dataize", symbolic, "--log-level=INFO", "--quiet"] ["[INFO]: Entered "]+          testCLISucceeded ["dataize", symbolic, "--log-level=INFO", "--quiet"] ["[INFO]: Started "]        it "gets stuck on every λ function when it is not given" $         withStdin sum' $@@ -2550,24 +2616,27 @@           testCLISucceeded ["morph", symbolic, "--locator=Q.@", "--protocol=" ++ path, "--quiet", "--sweet", "--hide-rho"] []         records <- readProtocol path         lines records-          `shouldBe` [ "𝕄(Φ.φ)"-                     , "  applied(𝑛.0.1) := 5  # 𝕄(Φ.φ)"-                     , "  applied(𝑛.0.2) := 𝑛.0.1.plus( x ↦ 6 )  # 𝕄(Φ.φ)"-                     , "  𝔼(L_number_plus)  # 𝕄(Φ.φ)"-                     , "    applied(𝑛.1.1) := 5  # 𝕄(Φ.a🌵0)"-                     , "    formation(𝑛.1.1)  # 𝔻(Φ.a🌵0)"-                     , "      applied(𝑛.1.2) := Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵0)"-                     , "      formation(𝑛.1.2)  # 𝔻(Φ.a🌵0)"-                     , "    𝛿1.1 := 40-14-00-00-00-00-00-00  # 𝔻(ξ.ρ)"-                     , "    applied(𝑛.1.3) := 6  # 𝕄(Φ.a🌵1)"-                     , "    formation(𝑛.1.3)  # 𝔻(Φ.a🌵1)"-                     , "      applied(𝑛.1.4) := Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵1)"-                     , "      formation(𝑛.1.4)  # 𝔻(Φ.a🌵1)"-                     , "    𝛿2.1 := 40-18-00-00-00-00-00-00  # 𝔻(ξ.x)"-                     , "    𝑛.1.5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛"-                     , "    applied(𝑛.1.6) := Φ.number( φ ↦ 𝜎1:λ )  # 𝕄(Φ.φ)"-                     , "    𝑛.1.7 := 𝑛.1.6  # 𝕄(𝑛.1.5)"-                     , "  applied(𝑛.0.3) := 𝑛.1.6.plus( x ↦ 7 )  # 𝕄(Φ.φ)"+          `shouldBe` [ "𝕄(Φ.φ):"+                     , "  𝑛·0·1 := 5"+                     , "  𝑛·0·2 := 𝑛·0·1.plus( x ↦ 6 )"+                     , "  𝔼(L_number_plus):"+                     , "    𝔻(Φ.a🌵0):"+                     , "      𝕄(Φ.a🌵0):"+                     , "        𝑛·1·1 := 5"+                     , "        𝑛·1·2 := Φ.bytes( φ ↦ 40-14-00-00-00-00-00-00:Δ )"+                     , "      𝛿·1·1 := 40-14-00-00-00-00-00-00  # 5.0"+                     , "    𝛿1·1 := 𝛿·1·1  # 𝔻(ξ.ρ)"+                     , "    𝔻(Φ.a🌵1):"+                     , "      𝕄(Φ.a🌵1):"+                     , "        𝑛·1·3 := 6"+                     , "        𝑛·1·4 := Φ.bytes( φ ↦ 40-18-00-00-00-00-00-00:Δ )"+                     , "      𝛿·1·2 := 40-18-00-00-00-00-00-00  # 6.0"+                     , "    𝛿2·1 := 𝛿·1·2  # 𝔻(ξ.x)"+                     , "    𝑛·1·5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛"+                     , "    𝕄(𝑛·1·5):"+                     , "      𝑛·1·6 := Φ.number( φ ↦ 𝜎1:λ )"+                     , "    𝑛·1·7 := 𝑛·1·6  # 𝕄(𝑛·1·5)"+                     , "  𝑛·0·3 := 𝑛·1·6.plus( x ↦ 7 )"                      ]      it "saves morphing steps to dir with --steps-dir" $@@ -2680,7 +2749,7 @@                     (["morph", "--symbolic=" ++ table, "--max-seconds=1", "--protocol=" ++ path, "--quiet"] ++ opts)                     ["--max-seconds=1"]               records <- readProtocol path-              dropWhile (== ' ') (last (lines records)) `shouldStartWith` "timeout(1)  # 𝕄("+              dropWhile (== ' ') (last (lines records)) `shouldBe` "timeout(1)"        it "writes the timeout once to the XML protocol of a deep run" $         ladder $ \table ->@@ -2728,13 +2797,13 @@        it "writes the firings of a binding after those of the bindings before it" $         recorded ["--jobs=2"]-          >>= (`shouldBe` ["# 𝕄(Φ.a)", "# 𝕄(Φ.a)", "# 𝕄(Φ.b)", "# 𝕄(Φ.b)"]) . map (dropWhile (/= '#')) . filter (isPrefixOf "  𝔼(")+          >>= (`shouldBe` ["  𝕄(Φ.a):", "    𝔼(L_number_plus):", "    𝔼(L_number_plus):", "  𝕄(Φ.b):", "    𝔼(L_number_plus):", "    𝔼(L_number_plus):"]) . filter (\line -> any (`isPrefixOf` line) ["  𝕄(", "    𝔼("])        it "numbers the symbols of the protocol the way the answer numbers them" $-        recorded ["--jobs=2"] >>= (`shouldSatisfy` elem "    𝑛.4.3 := Φ.number( φ ↦ ⟦ λ ⤍ 𝜎4 ⟧ )  # 𝑛")+        recorded ["--jobs=2"] >>= (`shouldSatisfy` elem "      𝑛·4·3 := Φ.number( φ ↦ ⟦ λ ⤍ 𝜎4 ⟧ )  # 𝑛")        it "names what a binding mints after the binding" $-        recorded ["--jobs=2"] >>= (`shouldSatisfy` any (isInfixOf "# 𝔻(Φ.a🌵4-0)"))+        recorded ["--jobs=2"] >>= (`shouldSatisfy` any (isInfixOf "𝔻(Φ.a🌵4-0)"))        it "writes the protocol one walk writes, the names a binding mints apart" $ do         one <- recorded ["--jobs=1"]@@ -2844,16 +2913,16 @@             ["b ↦ ⟦ φ ↦ 𝜎2:λ, plus(x) ↦ L_number_plus:λ ⟧"]        it "reduces the operands of a formation once per binding spelling it under proven" $-        recorded "proven" >>= (`shouldSatisfy` ((== 4) . length . filter (isInfixOf "𝛿1.")))+        recorded "proven" >>= (`shouldSatisfy` ((== 4) . length . filter (isInfixOf "𝛿1·")))        it "reduces the operands of a formation once for the run under plausible" $-        recorded "plausible" >>= (`shouldSatisfy` ((== 2) . length . filter (isInfixOf "𝛿1.")))+        recorded "plausible" >>= (`shouldSatisfy` ((== 2) . length . filter (isInfixOf "𝛿1·")))        it "writes a recalled firing at its own site under plausible" $         recorded "plausible" >>= (`shouldSatisfy` ((== 4) . length . filter (isInfixOf "𝔼(L_number_plus)")))        it "answers a recalled firing with the line of the first under plausible" $-        recorded "plausible" >>= (`shouldContain` ["    𝑛.4.2 := 𝑛.2.5  # 𝕄(𝑛.4.1)"])+        recorded "plausible" >>= (`shouldContain` ["      𝑛·4·2 := 𝑛·2·5  # 𝕄(𝑛·4·1)"])        it "dataizes to the same datum under plausible" $         withStdin chained $
test/DataizeSpec.hs view
@@ -173,14 +173,14 @@       looping $ \endless -> do         expr <- parseExpressionThrows "⟦ @ ↦ ⟦ λ ⤍ L_loop ⟧ ⟧"         minted <- newIORef 0-        dataize expr emptyState (ReduceContext ExRoot ExRoot Nothing 25 25 (Steps 40 0) Nothing minted Nothing Nothing 1 False True False False 1 Nothing Dataization [] Map.empty endless (building linked) reduction evaluation fired dontSaveStep dontSaveEval linked)+        dataize expr emptyState (ReduceContext ExRoot ExRoot Nothing 25 25 (Steps 40 0) Nothing minted Nothing Nothing 1 Nothing False True False False 1 Nothing Dataization [] Map.empty endless (building linked) reduction evaluation fired dontSaveStep dontSaveEval linked)           `shouldThrow` (\e -> "--max-steps=40" `isInfixOf` show (e :: SomeException))      it "parks the step limit as a residual with --partial" $       looping $ \endless -> do         expr <- parseExpressionThrows "⟦ @ ↦ ⟦ λ ⤍ L_loop ⟧ ⟧"         minted <- newIORef 0-        (outcome, _, _) <- dataize expr emptyState (ReduceContext ExRoot ExRoot Nothing 25 25 (Steps 40 0) Nothing minted Nothing Nothing 1 False True True False 1 Nothing Dataization [] Map.empty endless (building linked) reduction evaluation fired dontSaveStep dontSaveEval linked)+        (outcome, _, _) <- dataize expr emptyState (ReduceContext ExRoot ExRoot Nothing 25 25 (Steps 40 0) Nothing minted Nothing Nothing 1 Nothing False True True False 1 Nothing Dataization [] Map.empty endless (building linked) reduction evaluation fired dontSaveStep dontSaveEval linked)         case outcome of           Residual _ -> pure ()           Dataized bts -> expectationFailure ("expected a residual, dataized to " ++ show bts)@@ -216,30 +216,40 @@       (_, protocol) <- partially known "2.times(3).nope"       protocol         `shouldBe` unlines-          [ "  formation(⟦ bytes(φ) ↦ ⟦ not(ρ) ↦ L_bytes_not:λ, eq(ρ, b) ↦ L_bytes_eq:λ ⟧, bool(φ) ↦ ⟦ if(ρ, then, else) ↦ L_fork:λ ⟧, number(φ) ↦ ⟦ as-bytes ↦ φ, plus(ρ, x) ↦ L_number_plus:λ, times(ρ, x) ↦ L_number_times:λ, div(ρ, x) ↦ L_number_div:λ, gt(ρ, x) ↦ L_number_gt:λ, eq(ρ, x) ↦ ρ.as-bytes.eq( x.as-bytes ):φ, nope(ρ) ↦ L_number_nope:λ ⟧, φ ↦ 2.times( 3 ).nope ⟧)  # 𝔻(Φ)"-          , "    applied(𝑛.0.1) := 2  # 𝕄(Φ)"-          , "    applied(𝑛.0.2) := 𝑛.0.1.times( x ↦ 3 )  # 𝕄(Φ)"-          , "    𝔼(L_number_times)  # 𝕄(Φ)"-          , "      applied(𝑛.1.1) := 2  # 𝕄(Φ.a🌵17)"-          , "      formation(𝑛.1.1)  # 𝔻(Φ.a🌵17)"-          , "        applied(𝑛.1.2) := Φ.bytes( φ ↦ 40-00-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵17)"-          , "        formation(𝑛.1.2)  # 𝔻(Φ.a🌵17)"-          , "      𝛿1.1 := 40-00-00-00-00-00-00-00  # 𝔻(ξ.ρ)"-          , "      applied(𝑛.1.3) := 3  # 𝕄(Φ.a🌵18)"-          , "      formation(𝑛.1.3)  # 𝔻(Φ.a🌵18)"-          , "        applied(𝑛.1.4) := Φ.bytes( φ ↦ 40-08-00-00-00-00-00-00:Δ )  # 𝕄(Φ.a🌵18)"-          , "        formation(𝑛.1.4)  # 𝔻(Φ.a🌵18)"-          , "      𝛿2.1 := 40-08-00-00-00-00-00-00  # 𝔻(ξ.x)"-          , "      𝑛.1.5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛"-          , "      applied(𝑛.1.6) := Φ.number( φ ↦ 𝜎1:λ )  # 𝕄(Φ)"-          , "      𝑛.1.7 := 𝑛.1.6  # 𝕄(𝑛.1.5)"-          , "    unanswered(L_number_nope)  # 𝔻(⟦ ρ ↦ 𝑛.1.6, λ ⤍ L_number_nope ⟧)"+          [ "  𝔻(Φ):"+          , "    𝕄(Φ):"+          , "      𝑛·0·1 := 2"+          , "      𝑛·0·2 := 𝑛·0·1.times( x ↦ 3 )"+          , "      𝔼(L_number_times):"+          , "        𝔻(Φ.a🌵17):"+          , "          𝕄(Φ.a🌵17):"+          , "            𝑛·1·1 := 2"+          , "            𝑛·1·2 := Φ.bytes( φ ↦ 40-00-00-00-00-00-00-00:Δ )"+          , "          𝛿·1·1 := 40-00-00-00-00-00-00-00  # 2.0"+          , "        𝛿1·1 := 𝛿·1·1  # 𝔻(ξ.ρ)"+          , "        𝔻(Φ.a🌵18):"+          , "          𝕄(Φ.a🌵18):"+          , "            𝑛·1·3 := 3"+          , "            𝑛·1·4 := Φ.bytes( φ ↦ 40-08-00-00-00-00-00-00:Δ )"+          , "          𝛿·1·2 := 40-08-00-00-00-00-00-00  # 3.0"+          , "        𝛿2·1 := 𝛿·1·2  # 𝔻(ξ.x)"+          , "        𝑛·1·5 := Φ.number( φ ↦ 𝜎1:λ )  # 𝑛"+          , "        𝕄(𝑛·1·5):"+          , "          𝑛·1·6 := Φ.number( φ ↦ 𝜎1:λ )"+          , "        𝑛·1·7 := 𝑛·1·6  # 𝕄(𝑛·1·5)"+          , "    unanswered(L_number_nope)  # 𝔻(⟦ ρ ↦ 𝑛·1·6, λ ⤍ L_number_nope ⟧)"           ]     it "leaves an unanswered λ function dataized directly as the whole residue" $ do       ((outcome, chain), protocol) <- partially known "[[ L> Sym_arg_0 ]]"       outcome `shouldBe` Residual placeholder-      protocol `shouldBe` "  formation(⟦ bytes(φ) ↦ ⟦ not(ρ) ↦ L_bytes_not:λ, eq(ρ, b) ↦ L_bytes_eq:λ ⟧, bool(φ) ↦ ⟦ if(ρ, then, else) ↦ L_fork:λ ⟧, number(φ) ↦ ⟦ as-bytes ↦ φ, plus(ρ, x) ↦ L_number_plus:λ, times(ρ, x) ↦ L_number_times:λ, div(ρ, x) ↦ L_number_div:λ, gt(ρ, x) ↦ L_number_gt:λ, eq(ρ, x) ↦ ρ.as-bytes.eq( x.as-bytes ):φ, nope(ρ) ↦ L_number_nope:λ ⟧, φ ↦ Sym_arg_0:λ ⟧)  # 𝔻(Φ)\n    unanswered(Sym_arg_0)  # 𝔻(Sym_arg_0:λ)\n"+      protocol `shouldBe` "  𝔻(Φ):\n    unanswered(Sym_arg_0)  # 𝔻(Sym_arg_0:λ)\n"       map fst chain `shouldEndWith` [placeholder]+    it "closes a dataization with the datum the delta rule found" $ do+      (_, protocol) <- partially known "[[ @ -> [[ D> 01-02 ]] ]]"+      protocol `shouldBe` "  𝔻(Φ):\n    𝛿·0·1 := 01-02\n"+    it "continues the block of a dataization the box rule enters again at the same site" $ do+      (_, protocol) <- partially known "[[ @ -> [[ @ -> [[ D> 0A- ]] ]] ]]"+      protocol `shouldBe` "  𝔻(Φ):\n    𝛿·0·1 := 0A-\n"     it "still reaches the manufactured datum when nothing is stuck" $ do       ((outcome, _), _) <- partially known "2.times(3)"       outcome `shouldBe` Dataized (BtMany ["40", "45", "00", "00", "00", "00", "00", "00"])@@ -255,12 +265,12 @@     forM_       [         ( "--max-cycles"-        , \minted -> ReduceContext ExRoot ExRoot Nothing 25 0 (Steps 250 0) Nothing minted Nothing Nothing 1 True True False False 1 Nothing Dataization [] Map.empty emptyLambdas (building linked) reduction evaluation fired dontSaveStep dontSaveEval linked+        , \minted -> ReduceContext ExRoot ExRoot Nothing 25 0 (Steps 250 0) Nothing minted Nothing Nothing 1 Nothing True True False False 1 Nothing Dataization [] Map.empty emptyLambdas (building linked) reduction evaluation fired dontSaveStep dontSaveEval linked         , "--max-cycles=0"         )       ,         ( "--max-depth"-        , \minted -> ReduceContext ExRoot ExRoot Nothing 0 25 (Steps 250 0) Nothing minted Nothing Nothing 1 True True False False 1 Nothing Dataization [] Map.empty emptyLambdas (building linked) reduction evaluation fired dontSaveStep dontSaveEval linked+        , \minted -> ReduceContext ExRoot ExRoot Nothing 0 25 (Steps 250 0) Nothing minted Nothing Nothing 1 Nothing True True False False 1 Nothing Dataization [] Map.empty emptyLambdas (building linked) reduction evaluation fired dontSaveStep dontSaveEval linked         , "--max-depth=0"         )       ]@@ -273,12 +283,12 @@     it "does not throw without --depth-sensitive even once --max-depth is exhausted" $ do       expr <- parseExpressionThrows boxed       minted <- newIORef 0-      (value, _, _) <- dataize expr emptyState (ReduceContext ExRoot ExRoot Nothing 0 25 (Steps 250 0) Nothing minted Nothing Nothing 1 False True False False 1 Nothing Dataization [] Map.empty emptyLambdas (building linked) reduction evaluation fired dontSaveStep dontSaveEval linked)+      (value, _, _) <- dataize expr emptyState (ReduceContext ExRoot ExRoot Nothing 0 25 (Steps 250 0) Nothing minted Nothing Nothing 1 Nothing False True False False 1 Nothing Dataization [] Map.empty emptyLambdas (building linked) reduction evaluation fired dontSaveStep dontSaveEval linked)       value `shouldBe` Dataized (BtOne "00")     it "throws once --max-cycles is exhausted even without --depth-sensitive" $ do       expr <- parseExpressionThrows boxed       minted <- newIORef 0-      dataize expr emptyState (ReduceContext ExRoot ExRoot Nothing 25 0 (Steps 250 0) Nothing minted Nothing Nothing 1 False True False False 1 Nothing Dataization [] Map.empty emptyLambdas (building linked) reduction evaluation fired dontSaveStep dontSaveEval linked)+      dataize expr emptyState (ReduceContext ExRoot ExRoot Nothing 25 0 (Steps 250 0) Nothing minted Nothing Nothing 1 Nothing False True False False 1 Nothing Dataization [] Map.empty emptyLambdas (building linked) reduction evaluation fired dontSaveStep dontSaveEval linked)         `shouldThrow` (\e -> "--max-cycles=0" `isInfixOf` show (e :: SomeException))    describe "labels every step with a defined rule or operation" $ do
test/DepsSpec.hs view
@@ -5,13 +5,13 @@  module DepsSpec where -import AST (Argument (ArTau), Attribute (AtLabel, AtPhi), Binding (BiLambda, BiTau), Bytes (BtOne), Expression (ExApplication, ExDispatch, ExFormation, ExRoot, ExXi), Function (FnSymbol), symbols)+import AST (Argument (ArTau), Attribute (AtLabel, AtPhi), Binding (BiLambda, BiTau), Bytes (BtMany, BtOne), Expression (ExApplication, ExDispatch, ExFormation, ExRoot, ExXi), Function (FnSymbol), symbols) import Control.Exception (bracket) import Control.Monad (replicateM_, when) import Data.IORef (modifyIORef', newIORef, readIORef) import Data.List (isInfixOf, isPrefixOf) import Data.Time.Clock.POSIX (getPOSIXTime)-import Deps (Acyclic (Proven), Evaluation (EvAnswer, EvApplied, EvBuilt, EvComputed, EvDeferred, EvFiring, EvFormation, EvJoined, EvLooped, EvMinted, EvRun, EvTerm), Judgment (Morphing), Nesting (..), Protocol (..), dontSaveEval, dontSaveStep, emptyNesting, emptyProgress, emptyProtocol, endEval, endEvalXml, perSecond, progressed, renumbered, saveStep)+import Deps (Acyclic (Proven), Evaluation (EvAnswer, EvApplied, EvBuilt, EvComputed, EvData, EvDeferred, EvDelta, EvFiring, EvJoined, EvLooped, EvMinted, EvRun, EvStarted, EvTerm), Judgment (Dataization, Morphing), Nesting (..), Protocol (..), dontSaveEval, dontSaveStep, emptyNesting, emptyProgress, emptyProtocol, endEval, endEvalXml, perSecond, progressed, renumbered, resited, saveStep) import Fixtures (readUtf8, recorded, recordedXml) import GHC.Clock (getMonotonicTime) import Logger (LogLevel (DEBUG, ERROR, INFO), setLogConfig)@@ -69,7 +69,7 @@     it "passes every record on to the recording function it wraps" $ do       cursor <- newIORef (emptyProgress 0)       seen <- newIORef (0 :: Int)-      hSilence [stderr] (mapM_ (progressed cursor 3600 (const (pure "Φ.q")) (const (modifyIORef' seen (+ 1)))) [EvRun Morphing "Φ", EvFiring 1 "L_x" Morphing ExXi, EvFormation 2 ExRoot ExXi])+      hSilence [stderr] (mapM_ (progressed cursor 3600 (const (pure "Φ.q")) (const (modifyIORef' seen (+ 1)))) [EvRun Morphing "Φ", EvFiring 1 "L_x" Morphing ExXi, EvStarted 2 Dataization ExXi])       count <- readIORef seen       count `shouldBe` 3 @@ -79,11 +79,16 @@       captured <- hCapture_ [stderr] (replicateM_ 7 (progressed cursor 0 (const (pure "Φ.q")) dontSaveEval (EvFiring 1 "L_y" Morphing ExXi)))       last (lines captured) `shouldSatisfy` isInfixOf "fired 7 λ functions" -    it "counts the formations entered when the interval has passed" $ do+    it "counts the dataizations started when the interval has passed" $ do       setLogConfig INFO 25       cursor <- newIORef (emptyProgress 0)-      captured <- hCapture_ [stderr] (replicateM_ 4 (progressed cursor 0 (const (pure "Φ.q")) dontSaveEval (EvFormation 3 ExRoot ExXi)))-      last (lines captured) `shouldSatisfy` isInfixOf "Entered 4 formations"+      captured <- hCapture_ [stderr] (replicateM_ 4 (progressed cursor 0 (const (pure "Φ.q")) dontSaveEval (EvStarted 3 Dataization ExXi)))+      last (lines captured) `shouldSatisfy` isInfixOf "Started 4 dataizations"+    it "does not count a morphing as a dataization started" $ do+      setLogConfig INFO 25+      cursor <- newIORef (emptyProgress 0)+      captured <- hCapture_ [stderr] (mapM_ (progressed cursor 0 (const (pure "Φ.q")) dontSaveEval) [EvStarted 3 Morphing ExXi, EvStarted 2 Dataization ExXi])+      last (lines captured) `shouldSatisfy` isInfixOf "Started 1 dataizations"      it "names the site of the latest record" $ do       setLogConfig INFO 25@@ -136,32 +141,99 @@       case renumbered 3 4 (EvComputed 2 (ExFormation [BiTau (AtLabel "ш") (ExFormation [BiLambda (FnSymbol 2)])]) (ExFormation [BiTau (AtLabel "ш") (ExFormation [BiLambda (FnSymbol 6)])])) of         EvComputed _ before after -> (symbols before, symbols after) `shouldBe` ([2], [10])         _ -> expectationFailure "The record did not stay the record it was"+    it "raises the symbols the site of a started judgment carries above the floor" $+      case renumbered 1 3 (EvStarted 2 Morphing (ExFormation [BiLambda (FnSymbol 5)])) of+        EvStarted _ _ site -> symbols site `shouldBe` [8]+        _ -> expectationFailure "The record did not stay the record it was" +  describe "resited" $ do+    it "moves an application made at one site to another" $+      case resited (ExDispatch ExRoot (AtLabel "ёж")) ExXi (EvApplied 2 Morphing (ExFormation []) (ExFormation []) (ExDispatch ExRoot (AtLabel "ёж"))) of+        EvApplied _ _ _ _ site -> site `shouldBe` ExXi+        _ -> expectationFailure "The record did not stay the record it was"+    it "moves a firing asked for at one site to another" $+      case resited ExRoot ExXi (EvFiring 2 "L_ц" Morphing ExRoot) of+        EvFiring _ _ _ site -> site `shouldBe` ExXi+        _ -> expectationFailure "The record did not stay the record it was"+    it "moves a judgment started at one site to another" $+      case resited ExRoot ExXi (EvStarted 2 Morphing ExRoot) of+        EvStarted _ _ site -> site `shouldBe` ExXi+        _ -> expectationFailure "The record did not stay the record it was"+    it "leaves a record made at another site where it was" $+      case resited ExRoot ExXi (EvApplied 2 Morphing (ExFormation []) (ExFormation []) (ExDispatch ExRoot (AtLabel "щ"))) of+        EvApplied _ _ _ _ site -> site `shouldBe` ExDispatch ExRoot (AtLabel "щ")+        _ -> expectationFailure "The record did not stay the record it was"+   describe "saveEval" $ do     it "writes an application as a line binding what it made to a fresh 𝑛" $ do       (_, written) <- recorded (\record -> record (EvApplied 1 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) (ExDispatch ExRoot (AtLabel "w"))))-      written `shouldBe` "  applied(𝑛.0.1) := Φ.ёж( q ↦ ⟦⟧ )  # 𝕄(Φ.w)\n"+      written `shouldBe` "  𝑛·0·1 := Φ.ёж( q ↦ ⟦⟧ )  # 𝕄(Φ.w)\n"     it "spells an object an application made by its name on a later line" $ do       (_, written) <- recorded (\record -> mapM_ record [EvFiring 1 "L_щ" Morphing ExRoot, EvApplied 2 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) ExRoot, EvTerm 2 "𝑛1" (ExDispatch ExXi (AtLabel "z")) (ExFormation [BiTau (AtLabel "z") (ExFormation [BiTau (AtLabel "q") (ExFormation [])]), BiTau (AtLabel "у") (ExFormation [])])])-      last (lines written) `shouldBe` "    𝑛1.1 := ⟦ z ↦ 𝑛.1.1, у ↦ ⟦⟧ ⟧  # 𝕄(ξ.z)"+      last (lines written) `shouldBe` "    𝑛1·1 := ⟦ z ↦ 𝑛·1·1, у ↦ ⟦⟧ ⟧  # 𝕄(ξ.z)"     it "numbers the answer of a firing past the objects applications made inside it" $ do       (_, written) <- recorded (\record -> mapM_ record [EvFiring 1 "L_ю" Morphing ExRoot, EvBuilt 2 (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))), EvApplied 2 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) ExRoot, EvAnswer 2 (ExFormation [BiTau (AtLabel "q") (ExFormation [])])])-      last (lines written) `shouldBe` "    𝑛.1.3 := 𝑛.1.2  # 𝕄(𝑛.1.1)"+      last (lines written) `shouldBe` "    𝑛·1·3 := 𝑛·1·2  # 𝕄(𝑛·1·1)"     it "spells an application an earlier line wrote by its name in the argument of a later one" $ do       (_, written) <- recorded (\record -> mapM_ record [EvApplied 1 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) ExRoot, EvApplied 1 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "жук")) (ArTau (AtLabel "w") (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))))) (ExFormation [BiTau (AtLabel "w") (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation [])))]) ExRoot])-      last (lines written) `shouldBe` "  applied(𝑛.0.2) := Φ.жук( w ↦ 𝑛.0.1 )  # 𝕄(Φ)"+      last (lines written) `shouldBe` "  𝑛·0·2 := Φ.жук( w ↦ 𝑛·0·1 )  # 𝕄(Φ)"     it "spells an application made again by its head and argument rather than by the name of the first one" $ do       (_, written) <- recorded (\record -> replicateM_ 2 (record (EvApplied 1 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) ExRoot)))-      last (lines written) `shouldBe` "  applied(𝑛.0.2) := Φ.ёж( q ↦ ⟦⟧ )  # 𝕄(Φ)"+      last (lines written) `shouldBe` "  𝑛·0·2 := Φ.ёж( q ↦ ⟦⟧ )  # 𝕄(Φ)"     it "writes a deferred copy as the call it was made of even when an earlier application spelled that call" $ do       (_, written) <- recorded (\record -> mapM_ record [EvApplied 1 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation [BiLambda (FnSymbol 3)]))) (ExFormation [BiTau (AtLabel "q") (ExFormation [BiLambda (FnSymbol 3)])]) ExRoot, EvDeferred 1 4 Morphing (ExFormation [BiTau (AtLabel "q") (ExFormation [BiLambda (FnSymbol 3)])]) (Just (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation [BiLambda (FnSymbol 3)])))) ExRoot])       last (lines written) `shouldBe` "  deferred(𝜎4) := Φ.ёж( q ↦ 𝜎3:λ )  # 𝕄(Φ)"     it "spells an object the walk computed inside by the name its application gave it" $ do       (_, written) <- recorded (\record -> mapM_ record [EvFiring 1 "L_ъ" Morphing ExRoot, EvApplied 2 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExDispatch ExRoot (AtLabel "ф")))) (ExFormation [BiTau (AtLabel "q") (ExDispatch ExRoot (AtLabel "ф"))]) ExRoot, EvComputed 2 (ExFormation [BiTau (AtLabel "q") (ExDispatch ExRoot (AtLabel "ф"))]) (ExFormation [BiTau (AtLabel "q") (ExFormation [BiLambda (FnSymbol 8)])]), EvTerm 2 "𝑛1" (ExDispatch ExXi (AtLabel "z")) (ExFormation [BiTau (AtLabel "q") (ExFormation [BiLambda (FnSymbol 8)])])])-      last (lines written) `shouldBe` "    𝑛1.1 := 𝑛.1.1  # 𝕄(ξ.z)"+      last (lines written) `shouldBe` "    𝑛1·1 := 𝑛·1·1  # 𝕄(ξ.z)"     it "spells out an object the walk computed inside when no application named it" $ do       (_, written) <- recorded (\record -> mapM_ record [EvComputed 1 (ExFormation [BiTau (AtLabel "ю") ExRoot]) (ExFormation [BiTau (AtLabel "ю") (ExFormation [BiLambda (FnSymbol 3)])]), EvTerm 1 "𝑛1" (ExDispatch ExXi (AtLabel "z")) (ExFormation [BiTau (AtLabel "ю") (ExFormation [BiLambda (FnSymbol 3)])])])-      last (lines written) `shouldBe` "  𝑛1.0 := 𝜎3:λ:ю  # 𝕄(ξ.z)"+      last (lines written) `shouldBe` "  𝑛1·0 := 𝜎3:λ:ю  # 𝕄(ξ.z)"+    it "writes the datum the delta rule found under a name of its own" $ do+      (_, written) <- recorded (\record -> mapM_ record [EvFiring 1 "L_ж" Dataization ExRoot, EvDelta 2 (BtMany ["1F", "E0"]), EvDelta 2 (BtOne "33")])+      last (lines written) `shouldBe` "    𝛿·1·2 := 33-"+    it "comments a datum of eight bytes with the whole number it holds as a double" $ do+      (_, written) <- recorded (\record -> mapM_ record [EvFiring 1 "L_ж" Dataization ExRoot, EvDelta 2 (BtMany ["40", "45", "00", "00", "00", "00", "00", "00"])])+      last (lines written) `shouldBe` "    𝛿·1·1 := 40-45-00-00-00-00-00-00  # 42.0"+    it "comments a datum of eight bytes with the fraction it holds" $ do+      (_, written) <- recorded (\record -> mapM_ record [EvFiring 1 "L_ж" Dataization ExRoot, EvDelta 2 (BtMany ["C0", "09", "1E", "B8", "51", "EB", "85", "1F"])])+      last (lines written) `shouldBe` "    𝛿·1·1 := C0-09-1E-B8-51-EB-85-1F  # -3.14"+    it "spells the datum of an operand by the name the delta rule just gave it" $ do+      (_, written) <- recorded (\record -> mapM_ record [EvFiring 1 "L_ж" Dataization ExRoot, EvDelta 3 (BtOne "7F"), EvData 2 "𝛿1" (ExDispatch ExXi (AtLabel "щ")) (Right (BtOne "7F"))])+      last (lines written) `shouldBe` "    𝛿1·1 := 𝛿·1·1  # 𝔻(ξ.щ)"+    it "spells the datum of an operand in full when the line before it found no datum" $ do+      (_, written) <- recorded (\record -> mapM_ record [EvFiring 1 "L_ж" Dataization ExRoot, EvDelta 3 (BtOne "7F"), EvFiring 2 "L_з" Dataization ExRoot, EvData 2 "𝛿1" (ExDispatch ExXi (AtLabel "щ")) (Right (BtOne "7F"))])+      last (lines written) `shouldBe` "    𝛿1·1 := 7F-  # 𝔻(ξ.щ)"+    it "writes no heading for a judgment nothing stood under" $ do+      (_, written) <- recorded (\record -> mapM_ record [EvRun Dataization "Φ", EvStarted 1 Morphing (ExDispatch ExRoot (AtLabel "w")), EvDelta 1 (BtOne "0A")])+      lines written `shouldBe` ["𝔻(Φ):", "  𝛿·0·1 := 0A-"]+    it "writes the heading of a judgment above the first line under it and drops the comment naming it" $ do+      (_, written) <- recorded (\record -> mapM_ record [EvRun Dataization "Φ", EvStarted 1 Morphing (ExDispatch ExRoot (AtLabel "w")), EvApplied 2 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) (ExDispatch ExRoot (AtLabel "w"))])+      lines written `shouldBe` ["𝔻(Φ):", "  𝕄(Φ.w):", "    𝑛·0·1 := Φ.ёж( q ↦ ⟦⟧ )"]+    it "keeps the comment of a line made at a site other than the one of its block" $ do+      (_, written) <- recorded (\record -> mapM_ record [EvRun Morphing "Φ.w", EvApplied 1 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) (ExDispatch ExRoot (AtLabel "е"))])+      last (lines written) `shouldBe` "  𝑛·0·1 := Φ.ёж( q ↦ ⟦⟧ )  # 𝕄(Φ.е)"+    it "keeps the comment of a line made by a judgment other than the one of its block" $ do+      (_, written) <- recorded (\record -> mapM_ record [EvRun Dataization "Φ.w", EvApplied 1 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) (ExDispatch ExRoot (AtLabel "w"))])+      last (lines written) `shouldBe` "  𝑛·0·1 := Φ.ёж( q ↦ ⟦⟧ )  # 𝕄(Φ.w)"+    it "drops the comment of a firing the judgment of its block asked for at its site" $ do+      (_, written) <- recorded (\record -> mapM_ record [EvRun Dataization "Φ", EvFiring 1 "L_ш" Dataization ExRoot])+      last (lines written) `shouldBe` "  𝔼(L_ш):"+    it "keeps the comment of a line standing in a firing" $ do+      (_, written) <- recorded (\record -> mapM_ record [EvRun Morphing "Φ", EvFiring 1 "L_ш" Morphing ExRoot, EvApplied 2 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) ExRoot])+      last (lines written) `shouldBe` "    𝑛·1·1 := Φ.ёж( q ↦ ⟦⟧ )  # 𝕄(Φ)"+    it "writes one heading for two blocks of one judgment at one site in a row" $ do+      (_, written) <- recorded (\record -> mapM_ record [EvRun Dataization "Φ", EvStarted 1 Morphing (ExDispatch ExRoot (AtLabel "w")), EvApplied 2 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) (ExDispatch ExRoot (AtLabel "w")), EvStarted 1 Morphing (ExDispatch ExRoot (AtLabel "w")), EvApplied 2 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) (ExDispatch ExRoot (AtLabel "w"))])+      length (filter (== "  𝕄(Φ.w):") (lines written)) `shouldBe` 1+    it "writes the heading again for a block that follows a line beside it" $ do+      (_, written) <- recorded (\record -> mapM_ record [EvRun Dataization "Φ", EvStarted 1 Morphing (ExDispatch ExRoot (AtLabel "w")), EvApplied 2 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) (ExDispatch ExRoot (AtLabel "w")), EvDelta 1 (BtOne "0B"), EvStarted 1 Morphing (ExDispatch ExRoot (AtLabel "w")), EvApplied 2 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) (ExDispatch ExRoot (AtLabel "w"))])+      length (filter (== "  𝕄(Φ.w):") (lines written)) `shouldBe` 2+    it "keeps the mode of a cut made at the site of its block" $ do+      (_, written) <- recorded (\record -> mapM_ record [EvRun Morphing "Φ", EvLooped 1 Morphing Proven (ExFormation []) ExRoot Nothing])+      last (lines written) `shouldBe` "  looped(⟦⟧)  # proven"+    it "names the block over an answer by the line that built it" $ do+      (_, written) <- recorded (\record -> mapM_ record [EvRun Dataization "Φ", EvFiring 1 "L_ф" Dataization ExRoot, EvBuilt 2 (ExDispatch ExRoot (AtLabel "ю")), EvStarted 2 Morphing (ExDispatch ExRoot (AtLabel "ю")), EvApplied 3 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) (ExDispatch ExRoot (AtLabel "ю"))])+      lines written `shouldContain` ["    𝕄(𝑛·1·1):"]     it "writes no line for an object the walk computed inside" $ do       (_, written) <- recorded (\record -> record (EvComputed 1 (ExFormation [BiTau (AtLabel "ю") ExRoot]) (ExFormation [BiTau (AtLabel "ю") (ExFormation [BiLambda (FnSymbol 3)])])))       written `shouldBe` ""@@ -169,19 +241,43 @@   describe "saveEvalXml" $ do     it "writes an application as an element naming its head and holding its argument" $ do       (_, written) <- recordedXml (\record -> mapM_ record [EvRun Morphing "Φ.w", EvApplied 1 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) (ExDispatch ExRoot (AtLabel "w"))])-      lines written `shouldContain` ["  <applied meta=\"𝑛.0.1\" by=\"morph\" at=\"Φ.w\" of=\"Φ.ёж\"><attr name=\"q\">⟦⟧</attr></applied>"]+      lines written `shouldContain` ["  <applied meta=\"𝑛·0·1\" by=\"morph\" at=\"Φ.w\" of=\"Φ.ёж\"><attr name=\"q\">⟦⟧</attr></applied>"]     it "spells an argument an earlier application made by its name" $ do       (_, written) <- recordedXml (\record -> mapM_ record [EvRun Morphing "Φ", EvApplied 1 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) ExRoot, EvApplied 1 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "жук")) (ArTau (AtLabel "w") (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))))) (ExFormation [BiTau (AtLabel "w") (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation [])))]) ExRoot])-      lines written `shouldContain` ["  <applied meta=\"𝑛.0.2\" by=\"morph\" at=\"Φ\" of=\"Φ.жук\"><attr name=\"w\">𝑛.0.1</attr></applied>"]+      lines written `shouldContain` ["  <applied meta=\"𝑛·0·2\" by=\"morph\" at=\"Φ\" of=\"Φ.жук\"><attr name=\"w\">𝑛·0·1</attr></applied>"]     it "spells an argument that is a bare symbol as that symbol" $ do       (_, written) <- recordedXml (\record -> mapM_ record [EvRun Morphing "Φ", EvApplied 1 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "цапля")) (ArTau AtPhi (ExFormation [BiLambda (FnSymbol 7)]))) (ExFormation [BiTau AtPhi (ExFormation [BiLambda (FnSymbol 7)])]) ExRoot])-      lines written `shouldContain` ["  <applied meta=\"𝑛.0.1\" by=\"morph\" at=\"Φ\" of=\"Φ.цапля\"><attr name=\"φ\">𝜎7</attr></applied>"]+      lines written `shouldContain` ["  <applied meta=\"𝑛·0·1\" by=\"morph\" at=\"Φ\" of=\"Φ.цапля\"><attr name=\"φ\">𝜎7</attr></applied>"]     it "spells an object an application made by its name in a later element" $ do       (_, written) <- recordedXml (\record -> mapM_ record [EvRun Morphing "Φ", EvFiring 1 "L_ы" Morphing ExRoot, EvBuilt 2 (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))), EvApplied 2 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) ExRoot, EvAnswer 2 (ExFormation [BiTau (AtLabel "q") (ExFormation [])])])-      lines written `shouldContain` ["    <answer meta=\"𝑛.1.3\">𝑛.1.2</answer>"]+      lines written `shouldContain` ["    <answer meta=\"𝑛·1·3\">𝑛·1·2</answer>"]+    it "writes the datum the delta rule found as an element with its name" $ do+      (_, written) <- recordedXml (\record -> mapM_ record [EvRun Dataization "Φ", EvDelta 1 (BtMany ["0C", "D4"])])+      lines written `shouldContain` ["  <delta meta=\"𝛿·0·1\">0C-D4</delta>"]+    it "writes the double a datum of eight bytes holds as the number of its delta element" $ do+      (_, written) <- recordedXml (\record -> mapM_ record [EvRun Dataization "Φ", EvDelta 1 (BtMany ["C0", "09", "1E", "B8", "51", "EB", "85", "1F"])])+      lines written `shouldContain` ["  <delta meta=\"𝛿·0·1\" number=\"-3.14\">C0-09-1E-B8-51-EB-85-1F</delta>"]+    it "spells the datum of an operand by the name the delta rule just gave it in the markup" $ do+      (_, written) <- recordedXml (\record -> mapM_ record [EvRun Dataization "Φ", EvFiring 1 "L_ж" Dataization ExRoot, EvDelta 3 (BtOne "7F"), EvData 2 "𝛿1" (ExDispatch ExXi (AtLabel "щ")) (Right (BtOne "7F"))])+      lines written `shouldContain` ["    <bind meta=\"𝛿1·1\">𝛿·1·1</bind>"]     it "spells an object the walk computed inside by its name in a later element" $ do-      (_, written) <- recordedXml (\record -> mapM_ record [EvRun Morphing "Φ", EvApplied 1 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExDispatch ExRoot (AtLabel "ф")))) (ExFormation [BiTau (AtLabel "q") (ExDispatch ExRoot (AtLabel "ф"))]) ExRoot, EvComputed 1 (ExFormation [BiTau (AtLabel "q") (ExDispatch ExRoot (AtLabel "ф"))]) (ExFormation [BiTau (AtLabel "q") (ExFormation [BiLambda (FnSymbol 8)])]), EvFormation 1 (ExFormation [BiTau (AtLabel "q") (ExFormation [BiLambda (FnSymbol 8)])]) ExRoot])-      lines written `shouldContain` ["  <formation at=\"Φ\" term=\"𝑛.0.1\">"]+      (_, written) <- recordedXml (\record -> mapM_ record [EvRun Morphing "Φ", EvApplied 1 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExDispatch ExRoot (AtLabel "ф")))) (ExFormation [BiTau (AtLabel "q") (ExDispatch ExRoot (AtLabel "ф"))]) ExRoot, EvComputed 1 (ExFormation [BiTau (AtLabel "q") (ExDispatch ExRoot (AtLabel "ф"))]) (ExFormation [BiTau (AtLabel "q") (ExFormation [BiLambda (FnSymbol 8)])]), EvTerm 1 "𝑛1" (ExDispatch ExXi (AtLabel "z")) (ExFormation [BiTau (AtLabel "q") (ExFormation [BiLambda (FnSymbol 8)])])])+      lines written `shouldContain` ["  <bind meta=\"𝑛1·0\">𝑛·0·1</bind>"]+    it "writes a block as an element once an element stands in it" $ do+      (_, written) <- recordedXml (\record -> mapM_ record [EvRun Dataization "Φ", EvStarted 1 Morphing (ExDispatch ExRoot (AtLabel "w")), EvApplied 2 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) (ExDispatch ExRoot (AtLabel "w"))])+      lines written `shouldContain` ["  <morph at=\"Φ.w\">"]+    it "writes no element for a block nothing stands in" $ do+      (_, written) <- recordedXml (\record -> mapM_ record [EvRun Dataization "Φ", EvStarted 1 Morphing (ExDispatch ExRoot (AtLabel "w")), EvDelta 1 (BtOne "0C")])+      filter (isInfixOf "morph") (lines written) `shouldBe` []+    it "writes one element for two blocks of one judgment at one site in a row" $ do+      (_, written) <- recordedXml (\record -> mapM_ record [EvRun Dataization "Φ", EvStarted 1 Morphing (ExDispatch ExRoot (AtLabel "w")), EvApplied 2 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) (ExDispatch ExRoot (AtLabel "w")), EvStarted 1 Morphing (ExDispatch ExRoot (AtLabel "w")), EvApplied 2 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) (ExDispatch ExRoot (AtLabel "w"))])+      length (filter (isInfixOf "<morph") (lines written)) `shouldBe` 1+    it "closes a block element before the element that follows beside it" $ do+      (_, written) <- recordedXml (\record -> mapM_ record [EvRun Dataization "Φ", EvStarted 1 Morphing (ExDispatch ExRoot (AtLabel "w")), EvApplied 2 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) (ExDispatch ExRoot (AtLabel "w")), EvDelta 1 (BtOne "0D")])+      lines written `shouldContain` ["  </morph>", "  <delta meta=\"𝛿·0·1\">0D-</delta>"]+    it "names the element over an answer by the element that built it" $ do+      (_, written) <- recordedXml (\record -> mapM_ record [EvRun Dataization "Φ", EvFiring 1 "L_ф" Dataization ExRoot, EvBuilt 2 (ExDispatch ExRoot (AtLabel "ю")), EvStarted 2 Morphing (ExDispatch ExRoot (AtLabel "ю")), EvApplied 3 Morphing (ExApplication (ExDispatch ExRoot (AtLabel "ёж")) (ArTau (AtLabel "q") (ExFormation []))) (ExFormation [BiTau (AtLabel "q") (ExFormation [])]) (ExDispatch ExRoot (AtLabel "ю"))])+      lines written `shouldContain` ["    <morph at=\"𝑛·1·1\">"]    describe "perSecond" $ do     it "divides the firings by the seconds the run took" $
test/EvaluateSpec.hs view
@@ -75,6 +75,7 @@               , _steps = Steps (fromMaybe 250 steps) 0               , _symbolic = known               , _saveEval = record+              , _opened = Just (1, Morphing, loc)               }       record (EvRun Morphing (T.pack (printExpression loc)))       started expr ctx
test/Fixtures.hs view
@@ -55,7 +55,7 @@ defaultReduceContext :: Expression -> IO ReduceContext defaultReduceContext loc = do   minted <- newIORef 0-  pure (ReduceContext loc loc Nothing 25 25 (Steps 250 0) Nothing minted Nothing Nothing 1 False True False False 1 Nothing Morphing [] Map.empty emptyLambdas (building linked) reduction evaluation fired dontSaveStep dontSaveEval linked)+  pure (ReduceContext loc loc Nothing 25 25 (Steps 250 0) Nothing minted Nothing Nothing 1 Nothing False True False False 1 Nothing Morphing [] Map.empty emptyLambdas (building linked) reduction evaluation fired dontSaveStep dontSaveEval linked)  linked :: Engine linked = fromMaybe yaml compiled
test/LaTeXSpec.hs view
@@ -207,15 +207,14 @@           ]      forM_-      [ (Normalization, "\\phiNormalize")-      , (Morphing, "\\phiMorph")-      , (Dataization, "\\phiDataize")-      , (Evaluation, "\\phiEvaluate")-      , (Contextualization, "\\phiContextualize")+      [ (Normalization, "\\phiNormalize", "[\\nameref{r:tv}]")+      , (Morphing, "\\phiMorph", "[\\nameref{r:tv}]")+      , (Dataization, "\\phiDataize", "[\\nameref{r:tv}]")+      , (Evaluation, "\\phiEvaluate", "")+      , (Contextualization, "\\phiContextualize", "")       ]-      ( \(judgment, arrow) ->-          it ("ends a step taken by " ++ show judgment ++ " with " ++ arrow ++ " and opens the next one with it") $ do-            let reference = if judgment == Contextualization then "" else "[\\nameref{r:tv}]"+      ( \(judgment, arrow, reference) ->+          it ("ends a step taken by " ++ show judgment ++ " with " ++ arrow ++ reference ++ " and opens the next one with " ++ arrow) $ do             first <- parseExpressionThrows "[[ q -> Q.f ]]"             second <- parseExpressionThrows "[[ q -> Q.j ]]"             latex <- rewrittensToLatex ([(first, Just (judgment, "tv")), (second, Nothing)], False) defaultLatexContext
test/XMIRSpec.hs view
@@ -500,3 +500,12 @@       case result of         Left exc -> displayException exc `shouldContain` "Couldn't traverse though given XMIR"         Right _ -> expectationFailure "expected an exception"++  describe "XMIR name of a test" $ do+    it "accepts a formation named with a plus, the way EO names a test" $+      void (parseXMIRThrows "<object><o name=\"app\"><o name=\"+works\"/></o></object>" >>= xmirToPhi)+    it "accepts a formation named with a minus, the way EO names a test that must fail" $+      void (parseXMIRThrows "<object><o name=\"app\"><o name=\"-stops\"/></o></object>" >>= xmirToPhi)+    it "still refuses the rest of the name when it is not a label" $+      (parseXMIRThrows "<object><o name=\"app\"><o name=\"+Works\"/></o></object>" >>= xmirToPhi)+        `shouldThrow` anyException
test/YamlSpec.hs view
@@ -33,6 +33,16 @@  spec :: Spec spec = do+  describe "validates rewriting rule keys" $ do+    it "accepts rule labels and descriptions" $+      (decodeYaml' "name: foo\nlabel: foo-label\ndescription: A rule\npattern: '⟦ 𝜏1 ↦ 𝑒1 ⟧'\nresult: '𝑒1'" :: Either Yaml.ParseException Rule)+        `shouldSatisfy` (not . isLeft)+    it "rejects unknown top-level keys" $+      failsWith+        "Unknown key"+        (decodeYaml' "name: foo\npattern: '⟦ 𝜏1 ↦ 𝑒1 ⟧'\nresult: '𝑒1'\nunexpected: true" :: Either Yaml.ParseException Rule)+        `shouldBe` True+   describe "parses yaml rule" $ do     let resources = "test-resources/yaml-packs"     packs <- runIO (allPathsIn resources)