Imports
/- Copyright (c) 2026 Terence Rokop. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Terence Rokop -/ module public import Geb.Mathlib.Data.Tree.Ranked.Preorder import Geb.Mathlib.Data.W.Basic

The fold scan of a preorder spelling

RankedAlphabet.scanStep reads a preorder spelling right to left, carrying an incomplete block, a count of pending subterms and a liveness flag. At a completed block the symbol pops its arity from the count and pushes one, so the count is the height of a stack whose entries carry no data.

This module replaces that count by a stack of values of an arbitrary carrier and the pop-push by an application of an algebra of the ranked alphabet. toScan projects the resulting state onto RankedAlphabet.Scan by taking the stack's length, and toScan_foldScanStep shows the projection is a step homomorphism at every carrier and every algebra: the validity scan is the image of the fold scan under the terminal map, not a separate construction.

foldOut reads the final state as an Option, absent exactly where the word spells no term, and foldOut_eq identifies it with RankedAlphabet.parse followed by the fold. R.Term is the initial algebra of the alphabet, so that fold is the unique algebra morphism out of it.

Main definitions

    Geb.CobhamFold.symOf — the symbol a block denotes, refining RankedAlphabet.arOf, which returns only its arity.

    Geb.CobhamFold.Term.fold — the unique algebra morphism out of the term algebra.

    Geb.CobhamFold.FoldScan — the fold scan's state.

    Geb.CobhamFold.foldScanStep, Geb.CobhamFold.foldScanFrom, Geb.CobhamFold.foldScanFinal — one step, the scan from a state, and the scan from the initial state.

    Geb.CobhamFold.toScan — the projection onto RankedAlphabet.Scan.

    Geb.CobhamFold.foldOut — the final state read as an Option.

Main statements

    Geb.CobhamFold.arOf_eq_map_symOfRankedAlphabet.arOf is symOf followed by the arity.

    Geb.CobhamFold.toScan_foldScanStep, Geb.CobhamFold.toScan_foldScanFinal — the projection is a step homomorphism, and carries the whole scan.

    Geb.CobhamFold.mem_stack_foldScanFinal — every value on the scan's stack is one the algebra produced.

    Geb.CobhamFold.foldScanFrom_code — a completed block pops its arity's worth of stack and pushes the algebra applied to them.

    Geb.CobhamFold.foldScanFrom_ofFn — a family of spellings pushes one value each, in index order.

    Geb.CobhamFold.foldScanFrom_spell — a spelling pushes one value, the fold of the term it spells.

    Geb.CobhamFold.Term.fold_unique — the term algebra is initial, so Term.fold is the algebra morphism out of it rather than one of several.

    Geb.CobhamFold.Term.fold_map, Geb.CobhamFold.foldOut_map — fold fusion, and the agreement of two folds at different carriers whose algebras commute with a map.

    Geb.CobhamFold.foldOut_eq — the fold scan computes RankedAlphabet.parse followed by Term.fold.

    Geb.CobhamFold.buf_foldScanFinal, Geb.CobhamFold.length_stack_foldScanFinal, Geb.CobhamFold.length_buf_foldScanFinal_lt — the projection's consequences for the incomplete block and the stack's height, which every state layout over this scan consumes.

    Geb.CobhamFold.width_mul_depth_add_length_buf_scanFinal_le — the sharper bound on the pending count: the alphabet's width times the count, plus the incomplete block, is at most the word's length.

    Geb.CobhamFold.width_mul_depth_scanFinal_le — its corollary dropping the incomplete block, R.width * depth ≤ |w|.

Implementation notes

The stack's head is the value of the term spelled immediately to the right of the symbol being read, which is that symbol's child zero: scanning right to left, RankedAlphabet.scanFrom_append reads the later part of a word first, so within a symbol's children the last one scanned — and so the one pushed last — is child zero. foldScanStep therefore indexes the algebra's argument by position in the stack directly.

foldScanStep branches by dite where RankedAlphabet.scanStep branches by a match on decide: the arity branch needs the comparison's proof to index the stack, which a match on a Bool does not supply.

symOf is what RankedAlphabet.arOf would be if the scan needed the symbol rather than its arity; arOf_eq_map_symOf is what makes the two scans branch alike, and so what toScan_foldScanStep rests on.

width_mul_depth_add_length_buf_scanFinal_le sharpens RankedAlphabet.depth_scanFinal_le_length by the alphabet's width. The pending count rises only at a completed block, so it counts symbols rather than bits. The invariant carries the incomplete block's length because a partial block is progress toward the next increment; without that summand the induction does not close at the completing step. omega treats the products as atoms, so the completing step supplies the two linear facts relating them.

References

    [GambinoHyland2004]

Tags

ranked alphabet, preorder, scan, fold, catamorphism, initial algebra

@[expose] public sectionnamespace Geb.CobhamFoldopen RankedAlphabetuniverse u vvariable {α : Type u} {β : Type v}

The symbol a block denotes, absent at a block denoting none. RankedAlphabet.arOf returns that symbol's arity; a fold needs the symbol itself, to select the algebra's operation.

def symOf (R : RankedAlphabet) (v : ) : Option (Fin R.card) := if h : v < R.card then some v, h else none

The arity of a block's symbol is the arity of what symOf returns, so the validity scan and the fold scan take the same branch at every block.

theorem arOf_eq_map_symOf (R : RankedAlphabet) (v : ) : R.arOf v = (symOf R v).map R.arity := R:RankedAlphabetv:R.arOf v = Option.map R.arity (symOf R v) R:RankedAlphabetv:(if h : v < R.card then some (R.arity v, h) else none) = Option.map R.arity (if h : v < R.card then some v, h else none) R:RankedAlphabetv:h✝:v < R.cardsome (R.arity v, h✝) = Option.map R.arity (some v, h✝)R:RankedAlphabetv:h✝:¬v < R.cardnone = Option.map R.arity none R:RankedAlphabetv:h✝:v < R.cardsome (R.arity v, h✝) = Option.map R.arity (some v, h✝)R:RankedAlphabetv:h✝:¬v < R.cardnone = Option.map R.arity none All goals completed! 🐙

A block denotes the symbol it spells.

theorem symOf_decodeBits_code (R : RankedAlphabet) (i : Fin R.card) : symOf R (decodeBits (R.code i)) = some i := R:RankedAlphabeti:Fin R.cardsymOf R (decodeBits (R.code i)) = some i All goals completed! 🐙

The unique algebra morphism out of the term algebra: the fold of a term at an algebra of the ranked alphabet. RankedAlphabet.Term is that alphabet's W-type, so the morphism is its eliminator.

def Term.fold (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) : R.Term α := WType.elim α fun x alg x.1 x.2

The fold on a term, in the RankedAlphabet.Term.mk presentation.

@[simp] theorem Term.fold_mk (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (i : Fin R.card) (ch : Fin (R.arity i) R.Term) : Term.fold R alg (Term.mk R i ch) = alg i fun d Term.fold R alg (ch d) := rfl

The term algebra is initial: a map commuting with the algebra is the fold, so Term.fold is the algebra morphism out of it rather than one of several. RankedAlphabet.Term is a WType, so this is WType.elim_unique at the alphabet's shape and direction families, read at a point; the initiality it expresses is [GambinoHyland2004]'s for polynomial functors.

theorem Term.fold_unique (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (f : R.Term α) (hf : (i : Fin R.card) (ch : Fin (R.arity i) R.Term), f (Term.mk R i ch) = alg i fun d f (ch d)) : t : R.Term, f t = Term.fold R alg t := congrFun (WType.elim_unique (fun x : Σ i : Fin R.card, Fin (R.arity i) α alg x.1 x.2) f hf)

Fold fusion: a map commuting with two algebras carries one fold to the other. A corollary of initiality, and the statement that identifies the results of two fold constructions at different carriers.

theorem Term.fold_map (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (algV : (i : Fin R.card) (Fin (R.arity i) β) β) (e : α β) (he : (i : Fin R.card) (g : Fin (R.arity i) α), algV i (fun d e (g d)) = e (alg i g)) : t : R.Term, Term.fold R algV t = e (Term.fold R alg t) := fun t (Term.fold_unique R algV (fun t e (Term.fold R alg t)) (fun i ch α:Type uβ:Type vR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αalgV:(i : Fin R.card) (Fin (R.arity i) β) βe:α βhe: (i : Fin R.card) (g : Fin (R.arity i) α), (algV i fun d e (g d)) = e (alg i g)t:R.Termi:Fin R.cardch:Fin (R.arity i) R.Terme (fold R alg (Term.mk R i ch)) = algV i fun d e (fold R alg (ch d)) α:Type uβ:Type vR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αalgV:(i : Fin R.card) (Fin (R.arity i) β) βe:α βhe: (i : Fin R.card) (g : Fin (R.arity i) α), (algV i fun d e (g d)) = e (alg i g)t:R.Termi:Fin R.cardch:Fin (R.arity i) R.Terme (alg i fun d fold R alg (ch d)) = algV i fun d e (fold R alg (ch d)) All goals completed! 🐙) t).symm

The state of the fold scan: the bits of an incomplete block, the stack of values of the subterms already scanned, and whether the scan has failed. RankedAlphabet.Scan is this state with the stack replaced by its length.

The bits of an incomplete block, most recently read first.

The values of the subterms already scanned, the most recently completed first.

Whether the scan has not yet failed.

@[ext] structure FoldScan (α : Type u) where buf : List Bool stack : List α live : Bool

The projection onto the validity scan's state: the stack's length is the pending count.

def toScan (s : FoldScan α) : Scan := s.buf, s.stack.length, s.live

One step of the fold scan, reading one bit. A failed state absorbs. An incomplete block takes the bit; a complete one is decoded, and its symbol pops its arity's worth of stack, applies the algebra to them and pushes the result, failing when the block spells no symbol or the stack is short of the arity.

def foldScanStep (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (b : Bool) (s : FoldScan α) : FoldScan α := match s.live with | false => s | true => if (b :: s.buf).length = R.width then match symOf R (decodeBits (b :: s.buf)) with | none => [], s.stack, false | some i => if h : R.arity i s.stack.length then [], alg i (fun d s.stack[d.val]'(Nat.lt_of_lt_of_le d.isLt h)) :: s.stack.drop (R.arity i), true else [], s.stack, false else b :: s.buf, s.stack, true

The projection is a step homomorphism: the validity scan is the fold scan at every carrier and every algebra, read through the stack's length.

theorem toScan_foldScanStep (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (b : Bool) (s : FoldScan α) : toScan (foldScanStep R alg b s) = R.scanStep b (toScan s) := α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Bools:FoldScan αtoScan (foldScanStep R alg b s) = R.scanStep b (toScan s) α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αlive:BooltoScan (foldScanStep R alg b { buf := buf, stack := stack, live := live }) = R.scanStep b (toScan { buf := buf, stack := stack, live := live }) α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αlive:BooltoScan (foldScanStep R alg b { buf := buf, stack := stack, live := live }) = R.scanStep b { buf := buf, depth := stack.length, live := live } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αlive:BooltoScan (match { buf := buf, stack := stack, live := live }.live with | false => { buf := buf, stack := stack, live := live } | true => if (b :: { buf := buf, stack := stack, live := live }.buf).length = R.width then match symOf R (decodeBits (b :: { buf := buf, stack := stack, live := live }.buf)) with | none => { buf := [], stack := { buf := buf, stack := stack, live := live }.stack, live := false } | some i => if h : R.arity i { buf := buf, stack := stack, live := live }.stack.length then { buf := [], stack := (alg i fun d { buf := buf, stack := stack, live := live }.stack[d]) :: List.drop (R.arity i) { buf := buf, stack := stack, live := live }.stack, live := true } else { buf := [], stack := { buf := buf, stack := stack, live := live }.stack, live := false } else { buf := b :: { buf := buf, stack := stack, live := live }.buf, stack := { buf := buf, stack := stack, live := live }.stack, live := true }) = match { buf := buf, depth := stack.length, live := live }.live with | false => { buf := buf, depth := stack.length, live := live } | true => match decide ((b :: { buf := buf, depth := stack.length, live := live }.buf).length = R.width) with | false => { buf := b :: { buf := buf, depth := stack.length, live := live }.buf, depth := { buf := buf, depth := stack.length, live := live }.depth, live := true } | true => match R.arOf (decodeBits (b :: { buf := buf, depth := stack.length, live := live }.buf)) with | none => { buf := [], depth := { buf := buf, depth := stack.length, live := live }.depth, live := false } | some r => match decide (r { buf := buf, depth := stack.length, live := live }.depth) with | false => { buf := [], depth := { buf := buf, depth := stack.length, live := live }.depth, live := false } | true => { buf := [], depth := { buf := buf, depth := stack.length, live := live }.depth - r + 1, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αlive:BooltoScan (match live with | false => { buf := buf, stack := stack, live := live } | true => if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }) = match live with | false => { buf := buf, depth := stack.length, live := live } | true => match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := stack.length, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := stack.length, live := false } | some r => match decide (r stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - r + 1, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αtoScan (match false with | false => { buf := buf, stack := stack, live := false } | true => if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }) = match false with | false => { buf := buf, depth := stack.length, live := false } | true => match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := stack.length, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := stack.length, live := false } | some r => match decide (r stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - r + 1, live := true }α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αtoScan (match true with | false => { buf := buf, stack := stack, live := true } | true => if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }) = match true with | false => { buf := buf, depth := stack.length, live := true } | true => match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := stack.length, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := stack.length, live := false } | some r => match decide (r stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - r + 1, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αtoScan (match false with | false => { buf := buf, stack := stack, live := false } | true => if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }) = match false with | false => { buf := buf, depth := stack.length, live := false } | true => match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := stack.length, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := stack.length, live := false } | some r => match decide (r stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - r + 1, live := true } All goals completed! 🐙 α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αtoScan (match true with | false => { buf := buf, stack := stack, live := true } | true => if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }) = match true with | false => { buf := buf, depth := stack.length, live := true } | true => match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := stack.length, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := stack.length, live := false } | some r => match decide (r stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - r + 1, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αtoScan (if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }) = match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := stack.length, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := stack.length, live := false } | some r => match decide (r stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - r + 1, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αtoScan (if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }) = match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := stack.length, live := true } | true => match Option.map R.arity (symOf R (decodeBits (b :: buf))) with | none => { buf := [], depth := stack.length, live := false } | some r => match decide (r stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - r + 1, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.widthtoScan (if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }) = match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := stack.length, live := true } | true => match Option.map R.arity (symOf R (decodeBits (b :: buf))) with | none => { buf := [], depth := stack.length, live := false } | some r => match decide (r stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - r + 1, live := true }α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αhlen:¬(b :: buf).length = R.widthtoScan (if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }) = match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := stack.length, live := true } | true => match Option.map R.arity (symOf R (decodeBits (b :: buf))) with | none => { buf := [], depth := stack.length, live := false } | some r => match decide (r stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - r + 1, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.widthtoScan (if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }) = match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := stack.length, live := true } | true => match Option.map R.arity (symOf R (decodeBits (b :: buf))) with | none => { buf := [], depth := stack.length, live := false } | some r => match decide (r stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - r + 1, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.widthtoScan (match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }) = match true with | false => { buf := b :: buf, depth := stack.length, live := true } | true => match Option.map R.arity (symOf R (decodeBits (b :: buf))) with | none => { buf := [], depth := stack.length, live := false } | some r => match decide (r stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - r + 1, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.widthtoScan (match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }) = match Option.map R.arity (symOf R (decodeBits (b :: buf))) with | none => { buf := [], depth := stack.length, live := false } | some r => match decide (r stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - r + 1, live := true } match hsym : symOf R (decodeBits (b :: buf)) with α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.widthhsym:symOf R (decodeBits (b :: buf)) = nonetoScan (match none with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }) = match Option.map R.arity none with | none => { buf := [], depth := stack.length, live := false } | some r => match decide (r stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - r + 1, live := true } All goals completed! 🐙 α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.widthi:Fin R.cardhsym:symOf R (decodeBits (b :: buf)) = some itoScan (match some i with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }) = match Option.map R.arity (some i) with | none => { buf := [], depth := stack.length, live := false } | some r => match decide (r stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - r + 1, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.widthi:Fin R.cardhsym:symOf R (decodeBits (b :: buf)) = some itoScan (match some i with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }) = match some (R.arity i) with | none => { buf := [], depth := stack.length, live := false } | some r => match decide (r stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - r + 1, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.widthi:Fin R.cardhsym:symOf R (decodeBits (b :: buf)) = some itoScan (if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }) = match decide (R.arity i stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - R.arity i + 1, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.widthi:Fin R.cardhsym:symOf R (decodeBits (b :: buf)) = some ihle:R.arity i stack.lengthtoScan (if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }) = match decide (R.arity i stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - R.arity i + 1, live := true }α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.widthi:Fin R.cardhsym:symOf R (decodeBits (b :: buf)) = some ihle:¬R.arity i stack.lengthtoScan (if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }) = match decide (R.arity i stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - R.arity i + 1, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.widthi:Fin R.cardhsym:symOf R (decodeBits (b :: buf)) = some ihle:R.arity i stack.lengthtoScan (if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }) = match decide (R.arity i stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - R.arity i + 1, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.widthi:Fin R.cardhsym:symOf R (decodeBits (b :: buf)) = some ihle:R.arity i stack.lengthtoScan { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } = match true with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - R.arity i + 1, live := true } exact Scan.ext rfl (α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.widthi:Fin R.cardhsym:symOf R (decodeBits (b :: buf)) = some ihle:R.arity i stack.length(toScan { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true }).depth = (match true with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - R.arity i + 1, live := true }).depth All goals completed! 🐙) rfl α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.widthi:Fin R.cardhsym:symOf R (decodeBits (b :: buf)) = some ihle:¬R.arity i stack.lengthtoScan (if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }) = match decide (R.arity i stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - R.arity i + 1, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.widthi:Fin R.cardhsym:symOf R (decodeBits (b :: buf)) = some ihle:¬R.arity i stack.lengthtoScan { buf := [], stack := stack, live := false } = match false with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - R.arity i + 1, live := true } All goals completed! 🐙 α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αhlen:¬(b :: buf).length = R.widthtoScan (if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }) = match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := stack.length, live := true } | true => match Option.map R.arity (symOf R (decodeBits (b :: buf))) with | none => { buf := [], depth := stack.length, live := false } | some r => match decide (r stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - r + 1, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Boolbuf:List Boolstack:List αhlen:¬(b :: buf).length = R.widthtoScan { buf := b :: buf, stack := stack, live := true } = match false with | false => { buf := b :: buf, depth := stack.length, live := true } | true => match Option.map R.arity (symOf R (decodeBits (b :: buf))) with | none => { buf := [], depth := stack.length, live := false } | some r => match decide (r stack.length) with | false => { buf := [], depth := stack.length, live := false } | true => { buf := [], depth := stack.length - r + 1, live := true } All goals completed! 🐙

The fold scan of a word from a given state. foldr reads the word's last bit first, which is the processing order of a right-to-left scan.

def foldScanFrom (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (w : List Bool) (s : FoldScan α) : FoldScan α := w.foldr (foldScanStep R alg) s

The fold scan of a word from the initial state.

def foldScanFinal (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (w : List Bool) : FoldScan α := foldScanFrom R alg w [], [], true

The fold scan of the empty word.

@[simp] theorem foldScanFrom_nil (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (s : FoldScan α) : foldScanFrom R alg [] s = s := rfl

The fold scan of a word, one bit at a time.

@[simp] theorem foldScanFrom_cons (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (b : Bool) (w : List Bool) (s : FoldScan α) : foldScanFrom R alg (b :: w) s = foldScanStep R alg b (foldScanFrom R alg w s) := rfl

Every value on the fold scan's stack is one the algebra produced: the stack starts empty, and the completing pop is the only clause that pushes.

theorem mem_stack_foldScanFinal (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (P : α Prop) (hpush : (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)) : (w : List Bool), v (foldScanFinal R alg w).stack, P v := List.rec (fun v hv absurd hv (α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)v:αhv:v (foldScanFinal R alg []).stackv (foldScanFinal R alg []).stack All goals completed! 🐙)) fun b u ih v hv α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolih: v (foldScanFinal R alg u).stack, P vv:αhv:v (foldScanFinal R alg (b :: u)).stackP v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolih: v (foldScanFinal R alg u).stack, P vv:αhv:v (foldScanFinal R alg (b :: u)).stackhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)P v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolih: v (foldScanFinal R alg u).stack, P vv:αhv:v (match (foldScanFinal R alg u).live with | false => foldScanFinal R alg u | true => if (b :: (foldScanFinal R alg u).buf).length = R.width then match symOf R (decodeBits (b :: (foldScanFinal R alg u).buf)) with | none => { buf := [], stack := (foldScanFinal R alg u).stack, live := false } | some i => if h : R.arity i (foldScanFinal R alg u).stack.length then { buf := [], stack := (alg i fun d (foldScanFinal R alg u).stack[d]) :: List.drop (R.arity i) (foldScanFinal R alg u).stack, live := true } else { buf := [], stack := (foldScanFinal R alg u).stack, live := false } else { buf := b :: (foldScanFinal R alg u).buf, stack := (foldScanFinal R alg u).stack, live := true }).stackhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)P v -- `foldScanFinal R alg u` is a term, not a local variable, so `obtain` on -- it would introduce fresh locals and rewrite neither `hv` nor `ih`. The -- named equation is what carries the split into both. α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolih: v (foldScanFinal R alg u).stack, P vv:αhv:v (match (foldScanFinal R alg u).live with | false => foldScanFinal R alg u | true => if (b :: (foldScanFinal R alg u).buf).length = R.width then match symOf R (decodeBits (b :: (foldScanFinal R alg u).buf)) with | none => { buf := [], stack := (foldScanFinal R alg u).stack, live := false } | some i => if h : R.arity i (foldScanFinal R alg u).stack.length then { buf := [], stack := (alg i fun d (foldScanFinal R alg u).stack[d]) :: List.drop (R.arity i) (foldScanFinal R alg u).stack, live := true } else { buf := [], stack := (foldScanFinal R alg u).stack, live := false } else { buf := b :: (foldScanFinal R alg u).buf, stack := (foldScanFinal R alg u).stack, live := true }).stackhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αlive:Boolhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := live }P v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αlive:Boolih: v { buf := buf, stack := stack, live := live }.stack, P vhv:v (match { buf := buf, stack := stack, live := live }.live with | false => { buf := buf, stack := stack, live := live } | true => if (b :: { buf := buf, stack := stack, live := live }.buf).length = R.width then match symOf R (decodeBits (b :: { buf := buf, stack := stack, live := live }.buf)) with | none => { buf := [], stack := { buf := buf, stack := stack, live := live }.stack, live := false } | some i => if h : R.arity i { buf := buf, stack := stack, live := live }.stack.length then { buf := [], stack := (alg i fun d { buf := buf, stack := stack, live := live }.stack[d]) :: List.drop (R.arity i) { buf := buf, stack := stack, live := live }.stack, live := true } else { buf := [], stack := { buf := buf, stack := stack, live := live }.stack, live := false } else { buf := b :: { buf := buf, stack := stack, live := live }.buf, stack := { buf := buf, stack := stack, live := live }.stack, live := true }).stackhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := live }P v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αlive:Boolih: v stack, P vhv:v (match live with | false => { buf := buf, stack := stack, live := live } | true => if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }).stackhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := live }P v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhv:v (match false with | false => { buf := buf, stack := stack, live := false } | true => if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }).stackhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := false }P vα:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhv:v (match true with | false => { buf := buf, stack := stack, live := true } | true => if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }).stackhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }P v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhv:v (match false with | false => { buf := buf, stack := stack, live := false } | true => if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }).stackhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := false }P v All goals completed! 🐙 α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhv:v (match true with | false => { buf := buf, stack := stack, live := true } | true => if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }).stackhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }P v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhv:v (if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }).stackhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }P v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhv:v (if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }).stackhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:(b :: buf).length = R.widthP vα:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhv:v (if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }).stackhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:¬(b :: buf).length = R.widthP v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhv:v (if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }).stackhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:(b :: buf).length = R.widthP v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhv:v (match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }).stackhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:(b :: buf).length = R.widthP v match hsym : symOf R (decodeBits (b :: buf)) with α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhv:v (match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }).stackhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:(b :: buf).length = R.widthhsym:symOf R (decodeBits (b :: buf)) = noneP v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhv:v (match none with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }).stackhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:(b :: buf).length = R.widthhsym:symOf R (decodeBits (b :: buf)) = noneP v All goals completed! 🐙 α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhv:v (match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }).stackhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:(b :: buf).length = R.widthi:Fin R.cardhsym:symOf R (decodeBits (b :: buf)) = some iP v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:(b :: buf).length = R.widthi:Fin R.cardhv:v (match some i with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }).stackhsym:symOf R (decodeBits (b :: buf)) = some iP v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:(b :: buf).length = R.widthi:Fin R.cardhv:v (if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }).stackhsym:symOf R (decodeBits (b :: buf)) = some iP v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:(b :: buf).length = R.widthi:Fin R.cardhv:v (if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }).stackhsym:symOf R (decodeBits (b :: buf)) = some ihst:R.arity i stack.lengthP vα:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:(b :: buf).length = R.widthi:Fin R.cardhv:v (if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }).stackhsym:symOf R (decodeBits (b :: buf)) = some ihst:¬R.arity i stack.lengthP v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:(b :: buf).length = R.widthi:Fin R.cardhv:v (if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }).stackhsym:symOf R (decodeBits (b :: buf)) = some ihst:R.arity i stack.lengthP v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:(b :: buf).length = R.widthi:Fin R.cardhsym:symOf R (decodeBits (b :: buf)) = some ihst:R.arity i stack.lengthhv:v { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true }.stackP v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:(b :: buf).length = R.widthi:Fin R.cardhsym:symOf R (decodeBits (b :: buf)) = some ihst:R.arity i stack.lengthhv:v { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true }.stackh:v = alg i fun d stack[d]P vα:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:(b :: buf).length = R.widthi:Fin R.cardhsym:symOf R (decodeBits (b :: buf)) = some ihst:R.arity i stack.lengthhv:v { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true }.stackh:v List.drop (R.arity i) stackP v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:(b :: buf).length = R.widthi:Fin R.cardhsym:symOf R (decodeBits (b :: buf)) = some ihst:R.arity i stack.lengthhv:v { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true }.stackh:v = alg i fun d stack[d]P v All goals completed! 🐙 α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:(b :: buf).length = R.widthi:Fin R.cardhsym:symOf R (decodeBits (b :: buf)) = some ihst:R.arity i stack.lengthhv:v { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true }.stackh:v List.drop (R.arity i) stackP v All goals completed! 🐙 α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:(b :: buf).length = R.widthi:Fin R.cardhv:v (if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false }).stackhsym:symOf R (decodeBits (b :: buf)) = some ihst:¬R.arity i stack.lengthP v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:(b :: buf).length = R.widthi:Fin R.cardhv:v { buf := [], stack := stack, live := false }.stackhsym:symOf R (decodeBits (b :: buf)) = some ihst:¬R.arity i stack.lengthP v All goals completed! 🐙 α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhv:v (if (b :: buf).length = R.width then match symOf R (decodeBits (b :: buf)) with | none => { buf := [], stack := stack, live := false } | some i => if h : R.arity i stack.length then { buf := [], stack := (alg i fun d stack[d]) :: List.drop (R.arity i) stack, live := true } else { buf := [], stack := stack, live := false } else { buf := b :: buf, stack := stack, live := true }).stackhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:¬(b :: buf).length = R.widthP v α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αP:α Prophpush: (i : Fin R.card) (f : Fin (R.arity i) α), P (alg i f)b:Boolu:List Boolv:αhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)buf:List Boolstack:List αih: v stack, P vhv:v { buf := b :: buf, stack := stack, live := true }.stackhfs:foldScanFinal R alg u = { buf := buf, stack := stack, live := true }hlen:¬(b :: buf).length = R.widthP v All goals completed! 🐙

The fold scan of a concatenation reads the later part first.

theorem foldScanFrom_append (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (u v : List Bool) (s : FoldScan α) : foldScanFrom R alg (u ++ v) s = foldScanFrom R alg u (foldScanFrom R alg v s) := List.foldr_append

The projection carries the whole scan, not only one step.

theorem toScan_foldScanFrom (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (s : FoldScan α) : w : List Bool, toScan (foldScanFrom R alg w s) = R.scanFrom w (toScan s) := List.rec rfl fun b v ih α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αs:FoldScan αb:Boolv:List Boolih:toScan (foldScanFrom R alg v s) = R.scanFrom v (toScan s)toScan (foldScanFrom R alg (b :: v) s) = R.scanFrom (b :: v) (toScan s) All goals completed! 🐙

The projection of the fold scan from the initial state is the validity scan.

theorem toScan_foldScanFinal (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (w : List Bool) : toScan (foldScanFinal R alg w) = R.scanFinal w := toScan_foldScanFrom R alg [], [], true w

A word shorter than a block only accumulates, as it does in the validity scan.

theorem foldScanFrom_short (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (st : List α) (bs : List Bool) : u : List Bool, u.length + bs.length < R.width foldScanFrom R alg u bs, st, true = u ++ bs, st, true := List.rec (fun _ rfl) (fun b v ih hv α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αst:List αbs:List Boolb:Boolv:List Boolih:v.length + bs.length < R.width foldScanFrom R alg v { buf := bs, stack := st, live := true } = { buf := v ++ bs, stack := st, live := true }hv:(b :: v).length + bs.length < R.widthfoldScanFrom R alg (b :: v) { buf := bs, stack := st, live := true } = { buf := b :: v ++ bs, stack := st, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αst:List αbs:List Boolb:Boolv:List Boolih:v.length + bs.length < R.width foldScanFrom R alg v { buf := bs, stack := st, live := true } = { buf := v ++ bs, stack := st, live := true }hv:(b :: v).length + bs.length < R.width(match { buf := v ++ bs, stack := st, live := true }.live with | false => { buf := v ++ bs, stack := st, live := true } | true => if (b :: { buf := v ++ bs, stack := st, live := true }.buf).length = R.width then match symOf R (decodeBits (b :: { buf := v ++ bs, stack := st, live := true }.buf)) with | none => { buf := [], stack := { buf := v ++ bs, stack := st, live := true }.stack, live := false } | some i => if h : R.arity i { buf := v ++ bs, stack := st, live := true }.stack.length then { buf := [], stack := (alg i fun d { buf := v ++ bs, stack := st, live := true }.stack[d]) :: List.drop (R.arity i) { buf := v ++ bs, stack := st, live := true }.stack, live := true } else { buf := [], stack := { buf := v ++ bs, stack := st, live := true }.stack, live := false } else { buf := b :: { buf := v ++ bs, stack := st, live := true }.buf, stack := { buf := v ++ bs, stack := st, live := true }.stack, live := true }) = { buf := b :: v ++ bs, stack := st, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αst:List αbs:List Boolb:Boolv:List Boolih:v.length + bs.length < R.width foldScanFrom R alg v { buf := bs, stack := st, live := true } = { buf := v ++ bs, stack := st, live := true }hv:(b :: v).length + bs.length < R.width(if (b :: (v ++ bs)).length = R.width then match symOf R (decodeBits (b :: (v ++ bs))) with | none => { buf := [], stack := st, live := false } | some i => if h : R.arity i st.length then { buf := [], stack := (alg i fun d st[d]) :: List.drop (R.arity i) st, live := true } else { buf := [], stack := st, live := false } else { buf := b :: (v ++ bs), stack := st, live := true }) = { buf := b :: v ++ bs, stack := st, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αst:List αbs:List Boolb:Boolv:List Boolih:v.length + bs.length < R.width foldScanFrom R alg v { buf := bs, stack := st, live := true } = { buf := v ++ bs, stack := st, live := true }hv:(b :: v).length + bs.length < R.width{ buf := b :: (v ++ bs), stack := st, live := true } = { buf := b :: v ++ bs, stack := st, live := true } All goals completed! 🐙)

Reading a symbol's block from a state with no incomplete block whose stack begins with the symbol's arguments pops them and pushes the algebra applied to them.

theorem foldScanFrom_code (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (i : Fin R.card) (vals : Fin (R.arity i) α) (st : List α) : foldScanFrom R alg (R.code i) [], List.ofFn vals ++ st, true = [], alg i vals :: st, true := α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αi:Fin R.cardvals:Fin (R.arity i) αst:List αfoldScanFrom R alg (R.code i) { buf := [], stack := List.ofFn vals ++ st, live := true } = { buf := [], stack := alg i vals :: st, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αi:Fin R.cardvals:Fin (R.arity i) αst:List αb:Boolv:List Boolhcode:R.code i = b :: vfoldScanFrom R alg (R.code i) { buf := [], stack := List.ofFn vals ++ st, live := true } = { buf := [], stack := alg i vals :: st, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αi:Fin R.cardvals:Fin (R.arity i) αst:List αb:Boolv:List Boolhcode:R.code i = b :: vhw:(R.code i).length = R.widthfoldScanFrom R alg (R.code i) { buf := [], stack := List.ofFn vals ++ st, live := true } = { buf := [], stack := alg i vals :: st, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αi:Fin R.cardvals:Fin (R.arity i) αst:List αb:Boolv:List Boolhcode:R.code i = b :: vhw:v.length + 1 = R.widthfoldScanFrom R alg (R.code i) { buf := [], stack := List.ofFn vals ++ st, live := true } = { buf := [], stack := alg i vals :: st, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αi:Fin R.cardvals:Fin (R.arity i) αst:List αb:Boolv:List Boolhcode:R.code i = b :: vhw:v.length + 1 = R.widthhofFn:(List.ofFn vals).length = R.arity ifoldScanFrom R alg (R.code i) { buf := [], stack := List.ofFn vals ++ st, live := true } = { buf := [], stack := alg i vals :: st, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αi:Fin R.cardvals:Fin (R.arity i) αst:List αb:Boolv:List Boolhcode:R.code i = b :: vhw:v.length + 1 = R.widthhofFn:(List.ofFn vals).length = R.arity ihle:R.arity i (List.ofFn vals ++ st).lengthfoldScanFrom R alg (R.code i) { buf := [], stack := List.ofFn vals ++ st, live := true } = { buf := [], stack := alg i vals :: st, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αi:Fin R.cardvals:Fin (R.arity i) αst:List αb:Boolv:List Boolhcode:R.code i = b :: vhw:v.length + 1 = R.widthhofFn:(List.ofFn vals).length = R.arity ihle:R.arity i (List.ofFn vals ++ st).length(match { buf := v ++ [], stack := List.ofFn vals ++ st, live := true }.live with | false => { buf := v ++ [], stack := List.ofFn vals ++ st, live := true } | true => if (b :: { buf := v ++ [], stack := List.ofFn vals ++ st, live := true }.buf).length = R.width then match symOf R (decodeBits (b :: { buf := v ++ [], stack := List.ofFn vals ++ st, live := true }.buf)) with | none => { buf := [], stack := { buf := v ++ [], stack := List.ofFn vals ++ st, live := true }.stack, live := false } | some i_1 => if h : R.arity i_1 { buf := v ++ [], stack := List.ofFn vals ++ st, live := true }.stack.length then { buf := [], stack := (alg i_1 fun d { buf := v ++ [], stack := List.ofFn vals ++ st, live := true }.stack[d]) :: List.drop (R.arity i_1) { buf := v ++ [], stack := List.ofFn vals ++ st, live := true }.stack, live := true } else { buf := [], stack := { buf := v ++ [], stack := List.ofFn vals ++ st, live := true }.stack, live := false } else { buf := b :: { buf := v ++ [], stack := List.ofFn vals ++ st, live := true }.buf, stack := { buf := v ++ [], stack := List.ofFn vals ++ st, live := true }.stack, live := true }) = { buf := [], stack := alg i vals :: st, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αi:Fin R.cardvals:Fin (R.arity i) αst:List αb:Boolv:List Boolhcode:R.code i = b :: vhw:v.length + 1 = R.widthhofFn:(List.ofFn vals).length = R.arity ihle:R.arity i (List.ofFn vals ++ st).length(if (b :: v).length = R.width then match symOf R (decodeBits (b :: v)) with | none => { buf := [], stack := List.ofFn vals ++ st, live := false } | some i_1 => if h : R.arity i_1 (List.ofFn vals ++ st).length then { buf := [], stack := (alg i_1 fun d (List.ofFn vals ++ st)[d]) :: List.drop (R.arity i_1) (List.ofFn vals ++ st), live := true } else { buf := [], stack := List.ofFn vals ++ st, live := false } else { buf := b :: v, stack := List.ofFn vals ++ st, live := true }) = { buf := [], stack := alg i vals :: st, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αi:Fin R.cardvals:Fin (R.arity i) αst:List αb:Boolv:List Boolhcode:R.code i = b :: vhw:v.length + 1 = R.widthhofFn:(List.ofFn vals).length = R.arity ihle:R.arity i (List.ofFn vals ++ st).length(match some i with | none => { buf := [], stack := List.ofFn vals ++ st, live := false } | some i_1 => if h : R.arity i_1 (List.ofFn vals ++ st).length then { buf := [], stack := (alg i_1 fun d (List.ofFn vals ++ st)[d]) :: List.drop (R.arity i_1) (List.ofFn vals ++ st), live := true } else { buf := [], stack := List.ofFn vals ++ st, live := false }) = { buf := [], stack := alg i vals :: st, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αi:Fin R.cardvals:Fin (R.arity i) αst:List αb:Boolv:List Boolhcode:R.code i = b :: vhw:v.length + 1 = R.widthhofFn:(List.ofFn vals).length = R.arity ihle:R.arity i (List.ofFn vals ++ st).length(if h : R.arity i (List.ofFn vals ++ st).length then { buf := [], stack := (alg i fun d (List.ofFn vals ++ st)[d]) :: List.drop (R.arity i) (List.ofFn vals ++ st), live := true } else { buf := [], stack := List.ofFn vals ++ st, live := false }) = { buf := [], stack := alg i vals :: st, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αi:Fin R.cardvals:Fin (R.arity i) αst:List αb:Boolv:List Boolhcode:R.code i = b :: vhw:v.length + 1 = R.widthhofFn:(List.ofFn vals).length = R.arity ihle:R.arity i (List.ofFn vals ++ st).length{ buf := [], stack := (alg i fun d (List.ofFn vals ++ st)[d]) :: List.drop (R.arity i) (List.ofFn vals ++ st), live := true } = { buf := [], stack := alg i vals :: st, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αi:Fin R.cardvals:Fin (R.arity i) αst:List αb:Boolv:List Boolhcode:R.code i = b :: vhw:v.length + 1 = R.widthhofFn:(List.ofFn vals).length = R.arity ihle:R.arity i (List.ofFn vals ++ st).length{ buf := [], stack := (alg i fun d (List.ofFn vals ++ st)[d]) :: List.drop (R.arity i) (List.ofFn vals ++ st), live := true }.stack = { buf := [], stack := alg i vals :: st, live := true }.stack α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αi:Fin R.cardvals:Fin (R.arity i) αst:List αb:Boolv:List Boolhcode:R.code i = b :: vhw:v.length + 1 = R.widthhofFn:(List.ofFn vals).length = R.arity ihle:R.arity i (List.ofFn vals ++ st).lengthd:Fin (R.arity i)(List.ofFn vals ++ st)[d] = vals d α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αi:Fin R.cardvals:Fin (R.arity i) αst:List αb:Boolv:List Boolhcode:R.code i = b :: vhw:v.length + 1 = R.widthhofFn:(List.ofFn vals).length = R.arity ihle:R.arity i (List.ofFn vals ++ st).lengthd:Fin (R.arity i)hd:d < (List.ofFn vals).length(List.ofFn vals ++ st)[d] = vals d All goals completed! 🐙

The fold scan of a family of spellings pushes one value per spelling, in index order: the value of index zero ends on top.

theorem foldScanFrom_ofFn (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) : (n : ) (f : Fin n List Bool) (g : Fin n α), ( (d : Fin n) (t : List α), foldScanFrom R alg (f d) [], t, true = [], g d :: t, true) st : List α, foldScanFrom R alg (List.ofFn f).flatten [], st, true = [], List.ofFn g ++ st, true := Nat.rec (fun _ _ _ st α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αx✝²:Fin Nat.zero List Boolx✝¹:Fin Nat.zero αx✝: (d : Fin Nat.zero) (t : List α), foldScanFrom R alg (x✝² d) { buf := [], stack := t, live := true } = { buf := [], stack := x✝¹ d :: t, live := true }st:List αfoldScanFrom R alg (List.ofFn x✝²).flatten { buf := [], stack := st, live := true } = { buf := [], stack := List.ofFn x✝¹ ++ st, live := true } All goals completed! 🐙) (fun _ ih f g hf st α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αx✝:ih: (f : Fin x✝ List Bool) (g : Fin x✝ α), (∀ (d : Fin x✝) (t : List α), foldScanFrom R alg (f d) { buf := [], stack := t, live := true } = { buf := [], stack := g d :: t, live := true }) (st : List α), foldScanFrom R alg (List.ofFn f).flatten { buf := [], stack := st, live := true } = { buf := [], stack := List.ofFn g ++ st, live := true }f:Fin x✝.succ List Boolg:Fin x✝.succ αhf: (d : Fin x✝.succ) (t : List α), foldScanFrom R alg (f d) { buf := [], stack := t, live := true } = { buf := [], stack := g d :: t, live := true }st:List αfoldScanFrom R alg (List.ofFn f).flatten { buf := [], stack := st, live := true } = { buf := [], stack := List.ofFn g ++ st, live := true } All goals completed! 🐙)

A spelling pushes one value: the fold of the term it spells, whatever the stack before it.

theorem foldScanFrom_spell (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (t : R.Term) (st : List α) : foldScanFrom R alg (R.spell t) [], st, true = [], Term.fold R alg t :: st, true := Term.induction (motive := fun t st : List α, foldScanFrom R alg (R.spell t) [], st, true = [], Term.fold R alg t :: st, true) (fun i ch ih st α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αt:R.Termst✝:List αi:Fin R.cardch:Fin (R.arity i) R.Termih: (d : Fin (R.arity i)) (st : List α), foldScanFrom R alg (R.spell (ch d)) { buf := [], stack := st, live := true } = { buf := [], stack := Term.fold R alg (ch d) :: st, live := true }st:List αfoldScanFrom R alg (R.spell (Term.mk R i ch)) { buf := [], stack := st, live := true } = { buf := [], stack := Term.fold R alg (Term.mk R i ch) :: st, live := true } α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αt:R.Termst✝:List αi:Fin R.cardch:Fin (R.arity i) R.Termih: (d : Fin (R.arity i)) (st : List α), foldScanFrom R alg (R.spell (ch d)) { buf := [], stack := st, live := true } = { buf := [], stack := Term.fold R alg (ch d) :: st, live := true }st:List α{ buf := [], stack := (alg i fun d Term.fold R alg (ch d)) :: st, live := true } = { buf := [], stack := Term.fold R alg (Term.mk R i ch) :: st, live := true } All goals completed! 🐙) t st

The final state read as an Option: the value on top of the stack when the scan ends live, with no incomplete block and exactly one pending subterm, and absent otherwise. The three conditions are those of RankedAlphabet.validBool, read on the stack's length rather than on a count.

def foldOut (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (w : List Bool) : Option α := if (foldScanFinal R alg w).live && (foldScanFinal R alg w).buf.isEmpty && (foldScanFinal R alg w).stack.length == 1 then (foldScanFinal R alg w).stack.head? else none

The condition foldOut tests is the recognizer's verdict. The projection supplies it: the three fields the test reads are the three RankedAlphabet.validBool reads, and toScan carries each.

theorem foldOut_cond (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (w : List Bool) : ((foldScanFinal R alg w).live && (foldScanFinal R alg w).buf.isEmpty && (foldScanFinal R alg w).stack.length == 1) = R.validBool w := α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αw:List Bool((foldScanFinal R alg w).live && (foldScanFinal R alg w).buf.isEmpty && (foldScanFinal R alg w).stack.length == 1) = R.validBool w All goals completed! 🐙

A spelling folds to the fold of the term it spells.

theorem foldOut_spell (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (t : R.Term) : foldOut R alg (R.spell t) = some (Term.fold R alg t) := α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αt:R.TermfoldOut R alg (R.spell t) = some (Term.fold R alg t) α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αt:R.Term(if ({ buf := [], stack := [Term.fold R alg t], live := true }.live && { buf := [], stack := [Term.fold R alg t], live := true }.buf.isEmpty && { buf := [], stack := [Term.fold R alg t], live := true }.stack.length == 1) = true then { buf := [], stack := [Term.fold R alg t], live := true }.stack.head? else none) = some (Term.fold R alg t) All goals completed! 🐙

A word spelling no term folds to nothing: the condition foldOut tests is the recognizer's verdict, which RankedAlphabet.valid_iff_exists_spell places exactly at the spellings.

theorem foldOut_eq_none_of_not_valid (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (w : List Bool) (h : ¬ R.Valid w) : foldOut R alg w = none := α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αw:List Boolh:¬R.Valid wfoldOut R alg w = none α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αw:List Boolh:¬R.Valid w(if R.validBool w = true then (foldScanFinal R alg w).stack.head? else none) = none All goals completed! 🐙

The fold scan computes the decoding followed by the fold: the unique algebra morphism out of the term algebra, read off the spelling.

theorem foldOut_eq (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (w : List Bool) : foldOut R alg w = (R.parse w).map (Term.fold R alg) := α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αw:List BoolfoldOut R alg w = Option.map (Term.fold R alg) (R.parse w) match hp : R.parse w with α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αw:List Boolt:R.Termhp:R.parse w = some tfoldOut R alg w = Option.map (Term.fold R alg) (some t) α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αw:List Boolt:R.Termhp:R.parse w = some tfoldOut R alg w = some (Term.fold R alg t) α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αw:List Boolt:R.Termhp:R.parse w = some tfoldOut R alg (R.spell t) = some (Term.fold R alg t) All goals completed! 🐙 α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αw:List Boolhp:R.parse w = nonefoldOut R alg w = Option.map (Term.fold R alg) none α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αw:List Boolhp:R.parse w = nonefoldOut R alg w = none α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αw:List Boolhp:R.parse w = nonehv:R.Valid wFalse α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αw:List Boolhp:R.parse w = nonehv:none.isSome = trueFalse exact absurd hv (α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αw:List Boolhp:R.parse w = nonehv:none.isSome = true¬none.isSome = true All goals completed! 🐙)

One step raises the alphabet's width times the pending count, plus the incomplete block's length, by at most one. Every clause but the completing pop leaves the count alone; the pop raises it by at most one, and the block it consumes is worth the width.

theorem width_mul_depth_scanStep_le (R : RankedAlphabet) (b : Bool) (s : Scan) : R.width * (R.scanStep b s).depth + (R.scanStep b s).buf.length R.width * s.depth + s.buf.length + 1 := R:RankedAlphabetb:Bools:ScanR.width * (R.scanStep b s).depth + (R.scanStep b s).buf.length R.width * s.depth + s.buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:live:BoolR.width * (R.scanStep b { buf := buf, depth := depth, live := live }).depth + (R.scanStep b { buf := buf, depth := depth, live := live }).buf.length R.width * { buf := buf, depth := depth, live := live }.depth + { buf := buf, depth := depth, live := live }.buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:live:BoolR.width * (match { buf := buf, depth := depth, live := live }.live with | false => { buf := buf, depth := depth, live := live } | true => match decide ((b :: { buf := buf, depth := depth, live := live }.buf).length = R.width) with | false => { buf := b :: { buf := buf, depth := depth, live := live }.buf, depth := { buf := buf, depth := depth, live := live }.depth, live := true } | true => match R.arOf (decodeBits (b :: { buf := buf, depth := depth, live := live }.buf)) with | none => { buf := [], depth := { buf := buf, depth := depth, live := live }.depth, live := false } | some r => match decide (r { buf := buf, depth := depth, live := live }.depth) with | false => { buf := [], depth := { buf := buf, depth := depth, live := live }.depth, live := false } | true => { buf := [], depth := { buf := buf, depth := depth, live := live }.depth - r + 1, live := true }).depth + (match { buf := buf, depth := depth, live := live }.live with | false => { buf := buf, depth := depth, live := live } | true => match decide ((b :: { buf := buf, depth := depth, live := live }.buf).length = R.width) with | false => { buf := b :: { buf := buf, depth := depth, live := live }.buf, depth := { buf := buf, depth := depth, live := live }.depth, live := true } | true => match R.arOf (decodeBits (b :: { buf := buf, depth := depth, live := live }.buf)) with | none => { buf := [], depth := { buf := buf, depth := depth, live := live }.depth, live := false } | some r => match decide (r { buf := buf, depth := depth, live := live }.depth) with | false => { buf := [], depth := { buf := buf, depth := depth, live := live }.depth, live := false } | true => { buf := [], depth := { buf := buf, depth := depth, live := live }.depth - r + 1, live := true }).buf.length R.width * { buf := buf, depth := depth, live := live }.depth + { buf := buf, depth := depth, live := live }.buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:live:BoolR.width * (match live with | false => { buf := buf, depth := depth, live := live } | true => match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match live with | false => { buf := buf, depth := depth, live := live } | true => match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:R.width * (match false with | false => { buf := buf, depth := depth, live := false } | true => match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match false with | false => { buf := buf, depth := depth, live := false } | true => match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1R:RankedAlphabetb:Boolbuf:List Booldepth:R.width * (match true with | false => { buf := buf, depth := depth, live := true } | true => match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match true with | false => { buf := buf, depth := depth, live := true } | true => match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:R.width * (match false with | false => { buf := buf, depth := depth, live := false } | true => match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match false with | false => { buf := buf, depth := depth, live := false } | true => match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:R.width * depth + buf.length R.width * depth + buf.length + 1 All goals completed! 🐙 R:RankedAlphabetb:Boolbuf:List Booldepth:R.width * (match true with | false => { buf := buf, depth := depth, live := true } | true => match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match true with | false => { buf := buf, depth := depth, live := true } | true => match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:R.width * (match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match decide ((b :: buf).length = R.width) with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = falseR.width * (match false with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match false with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = trueR.width * (match true with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match true with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = falseR.width * (match false with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match false with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = falseR.width * depth + (b :: buf).length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = falseR.width * depth + (buf.length + 1) R.width * depth + buf.length + 1 All goals completed! 🐙 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = trueR.width * (match true with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match true with | false => { buf := b :: buf, depth := depth, live := true } | true => match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = trueR.width * (match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthR.width * (match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match R.arOf (decodeBits (b :: buf)) with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthR.width * (match none with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match none with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthval✝:R.width * (match some val✝ with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match some val✝ with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthR.width * (match none with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match none with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthR.width * depth + [].length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthR.width * depth + 0 R.width * depth + buf.length + 1 All goals completed! 🐙 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthval✝:R.width * (match some val✝ with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match some val✝ with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthr:R.width * (match some val✝ with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match some val✝ with | none => { buf := [], depth := depth, live := false } | some r => match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthr:R.width * (match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match decide (r depth) with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthr:R.width * (match false with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match false with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthr:R.width * (match true with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match true with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthr:R.width * (match false with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match false with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthr:R.width * depth + [].length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthr:R.width * depth + 0 R.width * depth + buf.length + 1 All goals completed! 🐙 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthr:R.width * (match true with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).depth + (match true with | false => { buf := [], depth := depth, live := false } | true => { buf := [], depth := depth - r + 1, live := true }).buf.length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthr:R.width * (depth - r + 1) + [].length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthr:h2:R.width * (depth - r + 1) R.width * (depth + 1)R.width * (depth - r + 1) + [].length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthr:h2:R.width * (depth - r + 1) R.width * (depth + 1)h3:R.width * (depth + 1) = R.width * depth + R.widthR.width * (depth - r + 1) + [].length R.width * depth + buf.length + 1 R:RankedAlphabetb:Boolbuf:List Booldepth:hc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthr:h2:R.width * (depth - r + 1) R.width * (depth + 1)h3:R.width * (depth + 1) = R.width * depth + R.widthR.width * (depth - r + 1) + 0 R.width * depth + buf.length + 1 All goals completed! 🐙

The incomplete block of the fold scan is the incomplete block of the validity scan, the projection carrying it.

theorem buf_foldScanFinal (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (w : List Bool) : (foldScanFinal R alg w).buf = (R.scanFinal w).buf := congrArg Scan.buf (toScan_foldScanFinal R alg w)

The stack's height is the validity scan's pending count.

theorem length_stack_foldScanFinal (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (w : List Bool) : (foldScanFinal R alg w).stack.length = (R.scanFinal w).depth := congrArg Scan.depth (toScan_foldScanFinal R alg w)

The fold scan's incomplete block never fills.

theorem length_buf_foldScanFinal_lt (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (w : List Bool) : (foldScanFinal R alg w).buf.length < R.width := α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αw:List Bool(foldScanFinal R alg w).buf.length < R.width α:Type uR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αw:List Bool(R.scanFinal w).buf.length < R.width All goals completed! 🐙

Two folds whose algebras commute with a map agree on results, up to that map, on every input. This is the equivalence between two fold constructions at different carriers: neither construction enters the statement, only the shared specification foldOut_eq gives them.

theorem foldOut_map (R : RankedAlphabet) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (algV : (i : Fin R.card) (Fin (R.arity i) β) β) (e : α β) (he : (i : Fin R.card) (g : Fin (R.arity i) α), algV i (fun d e (g d)) = e (alg i g)) (w : List Bool) : foldOut R algV w = (foldOut R alg w).map e := α:Type uβ:Type vR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αalgV:(i : Fin R.card) (Fin (R.arity i) β) βe:α βhe: (i : Fin R.card) (g : Fin (R.arity i) α), (algV i fun d e (g d)) = e (alg i g)w:List BoolfoldOut R algV w = Option.map e (foldOut R alg w) α:Type uβ:Type vR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αalgV:(i : Fin R.card) (Fin (R.arity i) β) βe:α βhe: (i : Fin R.card) (g : Fin (R.arity i) α), (algV i fun d e (g d)) = e (alg i g)w:List BoolOption.map (Term.fold R algV) (R.parse w) = Option.map e (Option.map (Term.fold R alg) (R.parse w)) match R.parse w with α:Type uβ:Type vR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αalgV:(i : Fin R.card) (Fin (R.arity i) β) βe:α βhe: (i : Fin R.card) (g : Fin (R.arity i) α), (algV i fun d e (g d)) = e (alg i g)w:List BoolOption.map (Term.fold R algV) none = Option.map e (Option.map (Term.fold R alg) none) All goals completed! 🐙 α:Type uβ:Type vR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αalgV:(i : Fin R.card) (Fin (R.arity i) β) βe:α βhe: (i : Fin R.card) (g : Fin (R.arity i) α), (algV i fun d e (g d)) = e (alg i g)w:List Boolt:R.TermOption.map (Term.fold R algV) (some t) = Option.map e (Option.map (Term.fold R alg) (some t)) α:Type uβ:Type vR:RankedAlphabetalg:(i : Fin R.card) (Fin (R.arity i) α) αalgV:(i : Fin R.card) (Fin (R.arity i) β) βe:α βhe: (i : Fin R.card) (g : Fin (R.arity i) α), (algV i fun d e (g d)) = e (alg i g)w:List Boolt:R.Termsome (e (Term.fold R alg t)) = Option.map e (some (Term.fold R alg t)) All goals completed! 🐙

The pending count rises only at a completed block, so the alphabet's width times the count, plus the length of the incomplete block, is at most the word's length. This sharpens RankedAlphabet.depth_scanFinal_le_length by the width: the count is a number of symbols, not of bits.

theorem width_mul_depth_add_length_buf_scanFinal_le (R : RankedAlphabet) (w : List Bool) : R.width * (R.scanFinal w).depth + (R.scanFinal w).buf.length w.length := List.rec (R:RankedAlphabetw:List BoolR.width * (R.scanFinal []).depth + (R.scanFinal []).buf.length [].length R:RankedAlphabetw:List BoolR.width * 0 + 0 0; All goals completed! 🐙) (fun b v ih R:RankedAlphabetw:List Boolb:Boolv:List Boolih:R.width * (R.scanFinal v).depth + (R.scanFinal v).buf.length v.lengthR.width * (R.scanFinal (b :: v)).depth + (R.scanFinal (b :: v)).buf.length (b :: v).length R:RankedAlphabetw:List Boolb:Boolv:List Boolih:R.width * (R.scanFinal v).depth + (R.scanFinal v).buf.length v.lengthR.width * (R.scanStep b (R.scanFinal v)).depth + (R.scanStep b (R.scanFinal v)).buf.length v.length + 1 All goals completed! 🐙) w

The pending count is at most the word's length divided by the block width, in the multiplied form a state layout consumes.

theorem width_mul_depth_scanFinal_le (R : RankedAlphabet) (w : List Bool) : R.width * (R.scanFinal w).depth w.length := Nat.le_trans (Nat.le_add_right _ _) (width_mul_depth_add_length_buf_scanFinal_le R w)
end Geb.CobhamFoldend