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.BasicThe 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_symOf — RankedAlphabet.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)
split isTrue R:RankedAlphabetv:ℕh✝:v < R.card⊢ some (R.arity ⟨v, h✝⟩) = Option.map R.arity (some ⟨v, h✝⟩)isFalse R:RankedAlphabetv:ℕh✝:¬v < R.card⊢ none = Option.map R.arity none <;> isTrue R:RankedAlphabetv:ℕh✝:v < R.card⊢ some (R.arity ⟨v, h✝⟩) = Option.map R.arity (some ⟨v, h✝⟩)isFalse R:RankedAlphabetv:ℕh✝:¬v < R.card⊢ none = Option.map R.arity none rfl 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 := by R:RankedAlphabeti:Fin R.card⊢ symOf R (decodeBits (R.code i)) = some i
rw [decodeBits_code, R:RankedAlphabeti:Fin R.card⊢ symOf R ↑i = some i symOf, R:RankedAlphabeti:Fin R.card⊢ (if h : ↑i < R.card then some ⟨↑i, h⟩ else none) = some i dite_eq_left i.isLt R:RankedAlphabeti:Fin R.card⊢ some ⟨↑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 ↦ by α: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.Term⊢ e (fold R alg (Term.mk R i ch)) = algV i fun d ↦ e (fold R alg (ch d))
rw [Term.fold_mk α: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.Term⊢ e (alg i fun d ↦ fold R alg (ch d)) = 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.Term⊢ e (alg i fun d ↦ fold R alg (ch d)) = algV i fun d ↦ e (fold R alg (ch d))
exact (he i fun d ↦ Term.fold R alg (ch d)).symm 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 : BoolThe projection onto the validity scan's state: the stack's length is the pending count.
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) := by α: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)
obtain ⟨buf, stack, live⟩ := s α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αb:Boolbuf:List Boolstack:List αlive:Bool⊢ toScan (foldScanStep R alg b { buf := buf, stack := stack, live := live }) =
R.scanStep b (toScan { buf := buf, stack := stack, live := live })
change toScan (foldScanStep R alg b ⟨buf, stack, live⟩) =
R.scanStep b ⟨buf, stack.length, live⟩ α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αb:Boolbuf:List Boolstack:List αlive:Bool⊢ toScan (foldScanStep R alg b { buf := buf, stack := stack, live := live }) =
R.scanStep b { buf := buf, depth := stack.length, live := live }
rw [foldScanStep, α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αb:Boolbuf:List Boolstack:List αlive:Bool⊢ toScan
(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 }) =
R.scanStep b { buf := buf, depth := stack.length, live := live } scanStep α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αb:Boolbuf:List Boolstack:List αlive:Bool⊢ toScan
(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:Bool⊢ toScan
(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 }
dsimp only α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αb:Boolbuf:List Boolstack:List αlive:Bool⊢ toScan
(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 }
cases live false α: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 }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 }
· false α: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 } rfl All goals completed! 🐙
· 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 } dsimp only 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 }
rw [arOf_eq_map_symOf 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 }] 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 }
by_cases hlen : (b :: buf).length = R.width pos α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.width⊢ 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 }neg α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αb:Boolbuf:List Boolstack:List αhlen:¬(b :: buf).length = R.width⊢ 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 }
· pos α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.width⊢ 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 } rw [ite_eq_left hlen, pos α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.width⊢ toScan
(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 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 } decide_eq_true hlen pos α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.width⊢ toScan
(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 }] pos α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.width⊢ toScan
(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 }
dsimp only pos α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αb:Boolbuf:List Boolstack:List αhlen:(b :: buf).length = R.width⊢ toScan
(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
| none => α: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)) = none⊢ toScan
(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 } rfl All goals completed! 🐙
| some i => α: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 i⊢ toScan
(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 }
rw [Option.map_some α: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 i⊢ toScan
(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 i⊢ toScan
(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 }
dsimp only α: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 i⊢ toScan
(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 }
by_cases hle : R.arity i ≤ stack.length pos α: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
(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 }neg α: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
(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 }
· pos α: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
(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 } rw [dite_eq_left hle, pos α: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 } =
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 } decide_eq_true hle pos α: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 } =
match true with
| false => { buf := [], depth := stack.length, live := false }
| true => { buf := [], depth := stack.length - R.arity i + 1, live := true }] pos α: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 } =
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 (by α: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 rw [toScan, α: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⊢ { buf := { buf := [], stack := (alg i fun d ↦ stack[↑d]) :: List.drop (R.arity i) stack, live := true }.buf,
depth :=
{ buf := [], stack := (alg i fun d ↦ stack[↑d]) :: List.drop (R.arity i) stack, live := true }.stack.length,
live :=
{ buf := [], stack := (alg i fun d ↦ stack[↑d]) :: List.drop (R.arity i) stack, live := true }.live }.depth =
(match true with
| false => { buf := [], depth := stack.length, live := false }
| true => { buf := [], depth := stack.length - R.arity i + 1, live := true }).depth List.length_cons, α: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⊢ { buf := { buf := [], stack := (alg i fun d ↦ stack[↑d]) :: List.drop (R.arity i) stack, live := true }.buf,
depth := (List.drop (R.arity i) stack).length + 1,
live :=
{ buf := [], stack := (alg i fun d ↦ stack[↑d]) :: List.drop (R.arity i) stack, live := true }.live }.depth =
(match true with
| false => { buf := [], depth := stack.length, live := false }
| true => { buf := [], depth := stack.length - R.arity i + 1, live := true }).depth List.length_drop α: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⊢ { buf := { buf := [], stack := (alg i fun d ↦ stack[↑d]) :: List.drop (R.arity i) stack, live := true }.buf,
depth := stack.length - R.arity i + 1,
live :=
{ buf := [], stack := (alg i fun d ↦ stack[↑d]) :: List.drop (R.arity i) stack, live := true }.live }.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
· neg α: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
(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 } rw [dite_eq_right hle, neg α: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 := 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 } decide_eq_false hle neg α: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 := stack, live := false } =
match false with
| false => { buf := [], depth := stack.length, live := false }
| true => { buf := [], depth := stack.length - R.arity i + 1, live := true }] neg α: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 := stack, live := false } =
match false with
| false => { buf := [], depth := stack.length, live := false }
| true => { buf := [], depth := stack.length - R.arity i + 1, live := true }
rfl All goals completed! 🐙
· neg α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αb:Boolbuf:List Boolstack:List αhlen:¬(b :: buf).length = R.width⊢ 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 } rw [ite_eq_right hlen, neg α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αb:Boolbuf:List Boolstack:List αhlen:¬(b :: buf).length = R.width⊢ toScan { 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 } decide_eq_false hlen neg α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αb:Boolbuf:List Boolstack:List αhlen:¬(b :: buf).length = R.width⊢ toScan { 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 }] neg α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αb:Boolbuf:List Boolstack:List αhlen:¬(b :: buf).length = R.width⊢ toScan { 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 }
rfl 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) sThe 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 := rflThe 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) :=
rflEvery 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 (by α: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 []).stack⊢ v ∉ (foldScanFinal R alg []).stack simp [foldScanFinal, foldScanFrom] All goals completed! 🐙))
fun b u ih v hv ↦ by α: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)).stack⊢ P v
have hcons : foldScanFinal R alg (b :: u) =
foldScanStep R alg b (foldScanFinal R alg u) := rfl α: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
rw [hcons, α: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 ∈ (foldScanStep R alg b (foldScanFinal R alg u)).stackhcons:foldScanFinal R alg (b :: u) = foldScanStep R alg b (foldScanFinal R alg u)⊢ P v foldScanStep α: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] at 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 ∈
(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.
rcases hfs : foldScanFinal R alg u with ⟨buf, stack, live⟩ α: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
rw [hfs α: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] at hv ih α: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
dsimp only at hv ih ⊢ α: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
cases live false α: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 vtrue α: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
· false α: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 exact ih v hv All goals completed! 🐙
· true α: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 dsimp only at hv true α: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
by_cases hlen : (b :: buf).length = R.width pos α: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.width⊢ P vneg α: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.width⊢ P v
· pos α: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.width⊢ P v rw [ite_eq_left hlen pos α: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.width⊢ P v] at hv pos α: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.width⊢ P v
match hsym : symOf R (decodeBits (b :: buf)) with
| none => α: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)) = none⊢ P v
rw [hsym α: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)) = none⊢ P v] at 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 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)) = none⊢ P v
exact ih v hv All goals completed! 🐙
| some i => α: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 i⊢ P v
rw [hsym α: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 i⊢ P v] at 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 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 i⊢ P v
dsimp only at 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 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 i⊢ P v
by_cases hst : R.arity i ≤ stack.length pos α: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.length⊢ P vneg α: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.length⊢ P v
· pos α: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.length⊢ P v rw [dite_eq_left hst pos α: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 }.stack⊢ P v] at hv pos α: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 }.stack⊢ P v
rcases List.mem_cons.mp hv with h | h pos.inl α: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 vpos.inr α: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) stack⊢ P v
· pos.inl α: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 exact h ▸ hpush i _ All goals completed! 🐙
· pos.inr α: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) stack⊢ P v exact ih v (List.mem_of_mem_drop h) All goals completed! 🐙
· neg α: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.length⊢ P v rw [dite_eq_right hst neg α: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.length⊢ P v] at hv neg α: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.length⊢ P v
exact ih v hv All goals completed! 🐙
· neg α: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.width⊢ P v rw [ite_eq_right hlen neg α: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.width⊢ P v] at hv neg α: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.width⊢ P v
exact ih v hv 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_appendThe 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 ↦ by α: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)
rw [foldScanFrom_cons, α: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 (foldScanStep R alg b (foldScanFrom R alg v s)) = R.scanFrom (b :: v) (toScan s) toScan_foldScanStep, α: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)⊢ R.scanStep b (toScan (foldScanFrom R alg v s)) = R.scanFrom (b :: v) (toScan s) 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)⊢ R.scanStep b (R.scanFrom v (toScan s)) = R.scanFrom (b :: v) (toScan s) scanFrom_cons α: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)⊢ R.scanStep b (R.scanFrom v (toScan s)) = R.scanStep b (R.scanFrom 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⟩ wA 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 ↦ by α: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⊢ foldScanFrom R alg (b :: v) { buf := bs, stack := st, live := true } =
{ buf := b :: v ++ bs, stack := st, live := true }
rw [foldScanFrom_cons, α: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⊢ foldScanStep R alg b (foldScanFrom R alg v { buf := bs, stack := st, live := true }) =
{ buf := b :: v ++ bs, stack := st, live := true } ih (by α: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⊢ v.length + bs.length < R.width simp only [List.length_cons] at 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:v.length + 1 + bs.length < R.width⊢ v.length + bs.length < R.width; omega All goals completed! 🐙),
foldScanStep α: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⊢ (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 }
dsimp only α: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 }
rw [ite_eq_right (by α: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⊢ ¬(b :: (v ++ bs)).length = R.width
simp only [List.length_cons, List.length_append] at 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:v.length + 1 + bs.length < R.width⊢ ¬v.length + bs.length + 1 = R.width
omega All goals completed! 🐙)] α: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 }
rfl 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⟩ := by α: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 }
obtain ⟨b, v, hcode⟩ : ∃ b v, R.code i = b :: v := by α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αi:Fin R.cardvals:Fin (R.arity i) → αst:List α⊢ ∃ b v, R.code i = b :: v
match hc : R.code i with
| [] => α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αi:Fin R.cardvals:Fin (R.arity i) → αst:List αhc:R.code i = []⊢ ∃ b v, [] = b :: v
have hw := length_code R i α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αi:Fin R.cardvals:Fin (R.arity i) → αst:List αhc:R.code i = []hw:(R.code i).length = R.width⊢ ∃ b v, [] = b :: v
rw [hc α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αi:Fin R.cardvals:Fin (R.arity i) → αst:List αhc:R.code i = []hw:[].length = R.width⊢ ∃ b v, [] = b :: v] at hw α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αi:Fin R.cardvals:Fin (R.arity i) → αst:List αhc:R.code i = []hw:[].length = R.width⊢ ∃ b v, [] = b :: v
exact absurd hw.symm (Nat.ne_of_gt R.width_pos) All goals completed! 🐙
| b :: v => α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αi:Fin R.cardvals:Fin (R.arity i) → αst:List αb:Boolv:List Boolhc:R.code i = b :: v⊢ ∃ b_1 v_1, b :: v = b_1 :: v_1 exact ⟨b, v, rfl⟩ α: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 :: v⊢ foldScanFrom R alg (R.code i) { buf := [], stack := List.ofFn vals ++ st, live := true } =
{ buf := [], stack := alg i vals :: st, live := true }
have hw := length_code R i α: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.width⊢ foldScanFrom R alg (R.code i) { buf := [], stack := List.ofFn vals ++ st, live := true } =
{ buf := [], stack := alg i vals :: st, live := true }
rw [hcode, α: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:(b :: v).length = R.width⊢ foldScanFrom R alg (R.code i) { buf := [], stack := List.ofFn vals ++ st, live := true } =
{ buf := [], stack := alg i vals :: st, live := true } List.length_cons α: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.width⊢ foldScanFrom R alg (R.code i) { buf := [], stack := List.ofFn vals ++ st, live := true } =
{ buf := [], stack := alg i vals :: st, live := true }] at hw α: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.width⊢ foldScanFrom R alg (R.code i) { buf := [], stack := List.ofFn vals ++ st, live := true } =
{ buf := [], stack := alg i vals :: st, live := true }
have hofFn : (List.ofFn vals).length = R.arity i := List.length_ofFn α: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 i⊢ foldScanFrom R alg (R.code i) { buf := [], stack := List.ofFn vals ++ st, live := true } =
{ buf := [], stack := alg i vals :: st, live := true }
have hle : R.arity i ≤ (List.ofFn vals ++ st).length := by
rw [List.length_append, α: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 i⊢ R.arity i ≤ (List.ofFn vals).length + st.length hofFn α: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 i⊢ R.arity i ≤ R.arity i + st.length] α: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 i⊢ R.arity i ≤ R.arity i + st.length
omega α: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⊢ foldScanFrom R alg (R.code i) { buf := [], stack := List.ofFn vals ++ st, live := true } =
{ buf := [], stack := alg i vals :: st, live := true }
rw [hcode, α: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⊢ foldScanFrom R alg (b :: v) { buf := [], stack := List.ofFn vals ++ st, live := true } =
{ buf := [], stack := alg i vals :: st, live := true } foldScanFrom_cons, α: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⊢ foldScanStep R alg b (foldScanFrom R alg v { buf := [], stack := List.ofFn vals ++ st, live := true }) =
{ buf := [], stack := alg i vals :: st, live := true }
foldScanFrom_short R alg (List.ofFn vals ++ st) [] v (by α: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⊢ v.length + [].length < R.width simp α: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⊢ v.length < R.width; omega All goals completed! 🐙),
foldScanStep α: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⊢ (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 }
simp only [List.append_nil] α: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 }
rw [ite_eq_left (by α: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⊢ (b :: v).length = R.width rw [List.length_cons α: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⊢ v.length + 1 = R.width] α: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⊢ v.length + 1 = R.width; omega All goals completed! 🐙), ← hcode, α: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 symOf R (decodeBits (R.code 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 } symOf_decodeBits_code α: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⊢ (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 }
dsimp only α: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 }
rw [dite_eq_left hle α: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 } =
{ buf := [], stack := alg i vals :: st, live := true }
refine FoldScan.ext rfl ?_ rfl α: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
refine congrArg₂ List.cons (congrArg (alg i) (funext fun d ↦ ?_))
(List.drop_left' hofFn) α: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
have hd : d.val < (List.ofFn vals).length := by α: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 } rw [hofFn α: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)⊢ ↑d < R.arity i] α: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)⊢ ↑d < R.arity i; exact d.isLt α: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
rw [List.getElem_append_left hd, α: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)[↑d] = vals d List.getElem_ofFn α: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⊢ vals ⟨↑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 ↦ by α: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 }
rw [List.ofFn_zero, α: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 [].flatten { buf := [], stack := st, live := true } =
{ buf := [], stack := List.ofFn x✝¹ ++ st, live := true } List.flatten_nil, α: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 [] { buf := [], stack := st, live := true } =
{ buf := [], stack := List.ofFn x✝¹ ++ st, live := true } foldScanFrom_nil, α: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 α⊢ { buf := [], stack := st, live := true } = { buf := [], stack := List.ofFn x✝¹ ++ st, live := true } List.ofFn_zero, α: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 α⊢ { buf := [], stack := st, live := true } = { buf := [], stack := [] ++ st, live := true }
List.nil_append α: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 α⊢ { buf := [], stack := st, live := true } = { buf := [], stack := st, live := true }] All goals completed! 🐙)
(fun _ ih f g hf st ↦ by α: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 }
rw [List.ofFn_succ, α: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 (f 0 :: List.ofFn fun i ↦ f i.succ).flatten { buf := [], stack := st, live := true } =
{ buf := [], stack := List.ofFn g ++ st, live := true } List.flatten_cons, α: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 (f 0 ++ (List.ofFn fun i ↦ f i.succ).flatten) { buf := [], stack := st, live := true } =
{ buf := [], stack := List.ofFn g ++ st, live := true } foldScanFrom_append, α: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 (f 0)
(foldScanFrom R alg (List.ofFn fun i ↦ f i.succ).flatten { buf := [], stack := st, live := true }) =
{ buf := [], stack := List.ofFn g ++ st, live := true }
ih (fun i ↦ f i.succ) (fun i ↦ g i.succ) (fun d t ↦ hf d.succ t) 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 (f 0) { buf := [], stack := (List.ofFn fun i ↦ g i.succ) ++ st, live := true } =
{ buf := [], stack := List.ofFn g ++ st, live := true }
hf 0 (List.ofFn (fun i ↦ g i.succ) ++ 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 α⊢ { buf := [], stack := g 0 :: ((List.ofFn fun i ↦ g i.succ) ++ st), live := true } =
{ buf := [], stack := List.ofFn g ++ st, live := true } List.ofFn_succ, α: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 α⊢ { buf := [], stack := g 0 :: ((List.ofFn fun i ↦ g i.succ) ++ st), live := true } =
{ buf := [], stack := (g 0 :: List.ofFn fun i ↦ g i.succ) ++ st, live := true } List.cons_append α: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 α⊢ { buf := [], stack := g 0 :: ((List.ofFn fun i ↦ g i.succ) ++ st), live := true } =
{ buf := [], stack := g 0 :: ((List.ofFn fun i ↦ g i.succ) ++ 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 ↦ by α: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 }
rw [spell_mk, α: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.code i ++ (List.ofFn fun d ↦ R.spell (ch d)).flatten) { buf := [], stack := st, live := true } =
{ buf := [], stack := Term.fold R alg (Term.mk R i ch) :: st, live := true } foldScanFrom_append, α: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.code i)
(foldScanFrom R alg (List.ofFn fun d ↦ R.spell (ch d)).flatten { buf := [], stack := st, live := true }) =
{ buf := [], stack := Term.fold R alg (Term.mk R i ch) :: st, live := true }
foldScanFrom_ofFn R alg (R.arity i) (fun d ↦ R.spell (ch d))
(fun d ↦ Term.fold R alg (ch d)) (fun d t ↦ ih d t) 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.code i) { buf := [], stack := (List.ofFn 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 }
foldScanFrom_code R alg i (fun d ↦ Term.fold R alg (ch d)) 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 α⊢ { 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 }] α: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 }
rfl 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 := by α: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
rw [validBool, α: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.scanFinal w).live && (R.scanFinal w).buf.isEmpty && (R.scanFinal w).depth == 1) ← toScan_foldScanFinal R alg 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) =
((toScan (foldScanFinal R alg w)).live && (toScan (foldScanFinal R alg w)).buf.isEmpty &&
(toScan (foldScanFinal R alg w)).depth == 1) toScan α: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) =
({ buf := (foldScanFinal R alg w).buf, depth := (foldScanFinal R alg w).stack.length,
live := (foldScanFinal R alg w).live }.live &&
{ buf := (foldScanFinal R alg w).buf, depth := (foldScanFinal R alg w).stack.length,
live := (foldScanFinal R alg w).live }.buf.isEmpty &&
{ buf := (foldScanFinal R alg w).buf, depth := (foldScanFinal R alg w).stack.length,
live := (foldScanFinal R alg w).live }.depth ==
1)] 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) := by α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αt:R.Term⊢ foldOut R alg (R.spell t) = some (Term.fold R alg t)
rw [foldOut, α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αt:R.Term⊢ (if
((foldScanFinal R alg (R.spell t)).live && (foldScanFinal R alg (R.spell t)).buf.isEmpty &&
(foldScanFinal R alg (R.spell t)).stack.length == 1) =
true then
(foldScanFinal R alg (R.spell t)).stack.head?
else none) =
some (Term.fold R alg t) foldScanFinal, α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αt:R.Term⊢ (if
((foldScanFrom R alg (R.spell t) { buf := [], stack := [], live := true }).live &&
(foldScanFrom R alg (R.spell t) { buf := [], stack := [], live := true }).buf.isEmpty &&
(foldScanFrom R alg (R.spell t) { buf := [], stack := [], live := true }).stack.length == 1) =
true then
(foldScanFrom R alg (R.spell t) { buf := [], stack := [], live := true }).stack.head?
else none) =
some (Term.fold R alg t) foldScanFrom_spell α: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)] α: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)
rfl 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 := by α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αw:List Boolh:¬R.Valid w⊢ foldOut R alg w = none
rw [foldOut, α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αw:List Boolh:¬R.Valid w⊢ (if
((foldScanFinal R alg w).live && (foldScanFinal R alg w).buf.isEmpty &&
(foldScanFinal R alg w).stack.length == 1) =
true then
(foldScanFinal R alg w).stack.head?
else none) =
none foldOut_cond α: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] α: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
exact ite_eq_right h 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) := by α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αw:List Bool⊢ foldOut R alg w = Option.map (Term.fold R alg) (R.parse w)
match hp : R.parse w with
| some t => α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αw:List Boolt:R.Termhp:R.parse w = some t⊢ foldOut R alg w = Option.map (Term.fold R alg) (some t)
rw [Option.map_some α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αw:List Boolt:R.Termhp:R.parse w = some t⊢ foldOut 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 t⊢ foldOut R alg w = some (Term.fold R alg t)
rw [← (parse_eq_some_iff R).mp hp α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αw:List Boolt:R.Termhp:R.parse w = some t⊢ foldOut R alg (R.spell t) = 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 t⊢ foldOut R alg (R.spell t) = some (Term.fold R alg t)
exact foldOut_spell R alg t All goals completed! 🐙
| none => α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αw:List Boolhp:R.parse w = none⊢ foldOut R alg w = Option.map (Term.fold R alg) none
rw [Option.map_none α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αw:List Boolhp:R.parse w = none⊢ foldOut R alg w = none] α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αw:List Boolhp:R.parse w = none⊢ foldOut R alg w = none
refine foldOut_eq_none_of_not_valid R alg w fun hv ↦ ?_ α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αw:List Boolhp:R.parse w = nonehv:R.Valid w⊢ False
rw [valid_iff_isSome_parse, α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αw:List Boolhp:R.parse w = nonehv:(R.parse w).isSome = true⊢ False hp α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αw:List Boolhp:R.parse w = nonehv:none.isSome = true⊢ False] at hv α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αw:List Boolhp:R.parse w = nonehv:none.isSome = true⊢ False
exact absurd hv (by α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αw:List Boolhp:R.parse w = nonehv:none.isSome = true⊢ ¬none.isSome = true simp 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 := by R:RankedAlphabetb:Bools:Scan⊢ R.width * (R.scanStep b s).depth + (R.scanStep b s).buf.length ≤ R.width * s.depth + s.buf.length + 1
obtain ⟨buf, depth, live⟩ := s R:RankedAlphabetb:Boolbuf:List Booldepth:ℕlive:Bool⊢ R.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
rw [scanStep R:RankedAlphabetb:Boolbuf:List Booldepth:ℕlive:Bool⊢ R.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:Bool⊢ R.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
dsimp only R:RankedAlphabetb:Boolbuf:List Booldepth:ℕlive:Bool⊢ R.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
cases live false 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 + 1true 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
· false 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 dsimp only false R:RankedAlphabetb:Boolbuf:List Booldepth:ℕ⊢ R.width * depth + buf.length ≤ R.width * depth + buf.length + 1
omega All goals completed! 🐙
· true 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 dsimp only true 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
cases hc : decide ((b :: buf).length = R.width) true.false R:RankedAlphabetb:Boolbuf:List Booldepth:ℕhc:decide ((b :: buf).length = R.width) = false⊢ R.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 + 1true.true R:RankedAlphabetb:Boolbuf:List Booldepth:ℕhc:decide ((b :: buf).length = R.width) = true⊢ R.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
· true.false R:RankedAlphabetb:Boolbuf:List Booldepth:ℕhc:decide ((b :: buf).length = R.width) = false⊢ R.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 dsimp only true.false R:RankedAlphabetb:Boolbuf:List Booldepth:ℕhc:decide ((b :: buf).length = R.width) = false⊢ R.width * depth + (b :: buf).length ≤ R.width * depth + buf.length + 1
simp only [List.length_cons] true.false R:RankedAlphabetb:Boolbuf:List Booldepth:ℕhc:decide ((b :: buf).length = R.width) = false⊢ R.width * depth + (buf.length + 1) ≤ R.width * depth + buf.length + 1
omega All goals completed! 🐙
· true.true R:RankedAlphabetb:Boolbuf:List Booldepth:ℕhc:decide ((b :: buf).length = R.width) = true⊢ R.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 dsimp only true.true R:RankedAlphabetb:Boolbuf:List Booldepth:ℕhc:decide ((b :: buf).length = R.width) = true⊢ R.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
have hbw : buf.length + 1 = R.width := by R:RankedAlphabetb:Bools:Scan⊢ R.width * (R.scanStep b s).depth + (R.scanStep b s).buf.length ≤ R.width * s.depth + s.buf.length + 1
have hd := of_decide_eq_true hc R:RankedAlphabetb:Boolbuf:List Booldepth:ℕhc:decide ((b :: buf).length = R.width) = truehd:(b :: buf).length = R.width⊢ buf.length + 1 = R.width
rw [List.length_cons R:RankedAlphabetb:Boolbuf:List Booldepth:ℕhc:decide ((b :: buf).length = R.width) = truehd:buf.length + 1 = R.width⊢ buf.length + 1 = R.width] at hd R:RankedAlphabetb:Boolbuf:List Booldepth:ℕhc:decide ((b :: buf).length = R.width) = truehd:buf.length + 1 = R.width⊢ buf.length + 1 = R.width
omega true.true R:RankedAlphabetb:Boolbuf:List Booldepth:ℕhc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.width⊢ R.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
cases R.arOf (decodeBits (b :: buf)) true.true.none R:RankedAlphabetb:Boolbuf:List Booldepth:ℕhc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.width⊢ R.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 + 1true.true.some 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
· true.true.none R:RankedAlphabetb:Boolbuf:List Booldepth:ℕhc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.width⊢ R.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 dsimp only true.true.none R:RankedAlphabetb:Boolbuf:List Booldepth:ℕhc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.width⊢ R.width * depth + [].length ≤ R.width * depth + buf.length + 1
simp only [List.length_nil] true.true.none R:RankedAlphabetb:Boolbuf:List Booldepth:ℕhc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.width⊢ R.width * depth + 0 ≤ R.width * depth + buf.length + 1
omega All goals completed! 🐙
· true.true.some 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 rename_i r true.true.some 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
dsimp only true.true.some 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
cases decide (r ≤ depth) true.true.some.false 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 + 1true.true.some.true 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
· true.true.some.false 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 dsimp only true.true.some.false 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
simp only [List.length_nil] true.true.some.false 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
omega All goals completed! 🐙
· true.true.some.true 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 dsimp only true.true.some.true 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
have h2 : R.width * (depth - r + 1) ≤ R.width * (depth + 1) :=
Nat.mul_le_mul_left _ (by R:RankedAlphabetb:Boolbuf:List Booldepth:ℕhc:decide ((b :: buf).length = R.width) = truehbw:buf.length + 1 = R.widthr:ℕ⊢ depth - r + 1 ≤ depth + 1 omega All goals completed! 🐙) true.true.some.true 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
have h3 : R.width * (depth + 1) = R.width * depth + R.width :=
Nat.mul_succ _ _ true.true.some.true 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.width⊢ R.width * (depth - r + 1) + [].length ≤ R.width * depth + buf.length + 1
simp only [List.length_nil] true.true.some.true 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.width⊢ R.width * (depth - r + 1) + 0 ≤ R.width * depth + buf.length + 1
omega 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 := by α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αw:List Bool⊢ (foldScanFinal R alg w).buf.length < R.width
rw [buf_foldScanFinal α:Type uR:RankedAlphabetalg:(i : Fin R.card) → (Fin (R.arity i) → α) → αw:List Bool⊢ (R.scanFinal 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
exact length_buf_scanFinal_lt R w 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 := by α: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 Bool⊢ foldOut R algV w = Option.map e (foldOut R alg w)
rw [foldOut_eq, α: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 Bool⊢ Option.map (Term.fold R algV) (R.parse w) = Option.map e (foldOut R alg w) foldOut_eq α: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 Bool⊢ Option.map (Term.fold R algV) (R.parse w) = Option.map e (Option.map (Term.fold R alg) (R.parse 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 Bool⊢ Option.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
| none => α: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 Bool⊢ Option.map (Term.fold R algV) none = Option.map e (Option.map (Term.fold R alg) none) rfl All goals completed! 🐙
| 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.Term⊢ Option.map (Term.fold R algV) (some t) = Option.map e (Option.map (Term.fold R alg) (some t))
rw [Option.map_some, α: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.Term⊢ some (Term.fold R algV t) = Option.map e (Option.map (Term.fold R alg) (some t)) Option.map_some, α: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.Term⊢ some (Term.fold R algV t) = Option.map e (some (Term.fold R alg t)) Term.fold_map R alg algV e he 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.Term⊢ some (e (Term.fold R alg t)) = Option.map e (some (Term.fold R alg 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.Term⊢ some (e (Term.fold R alg t)) = Option.map e (some (Term.fold R alg t))
rfl 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 (by R:RankedAlphabetw:List Bool⊢ R.width * (R.scanFinal []).depth + (R.scanFinal []).buf.length ≤ [].length simp only [scanFinal_nil, List.length_nil] R:RankedAlphabetw:List Bool⊢ R.width * 0 + 0 ≤ 0; omega All goals completed! 🐙)
(fun b v ih ↦ by R:RankedAlphabetw:List Boolb:Boolv:List Boolih:R.width * (R.scanFinal v).depth + (R.scanFinal v).buf.length ≤ v.length⊢ R.width * (R.scanFinal (b :: v)).depth + (R.scanFinal (b :: v)).buf.length ≤ (b :: v).length
rw [scanFinal_cons, R:RankedAlphabetw:List Boolb:Boolv:List Boolih:R.width * (R.scanFinal v).depth + (R.scanFinal v).buf.length ≤ v.length⊢ R.width * (R.scanStep b (R.scanFinal v)).depth + (R.scanStep b (R.scanFinal v)).buf.length ≤ (b :: v).length List.length_cons R:RankedAlphabetw:List Boolb:Boolv:List Boolih:R.width * (R.scanFinal v).depth + (R.scanFinal v).buf.length ≤ v.length⊢ R.width * (R.scanStep b (R.scanFinal v)).depth + (R.scanStep b (R.scanFinal v)).buf.length ≤ v.length + 1] R:RankedAlphabetw:List Boolb:Boolv:List Boolih:R.width * (R.scanFinal v).depth + (R.scanFinal v).buf.length ≤ v.length⊢ R.width * (R.scanStep b (R.scanFinal v)).depth + (R.scanStep b (R.scanFinal v)).buf.length ≤ v.length + 1
exact Nat.le_trans (width_mul_depth_scanStep_le R b (R.scanFinal v))
(Nat.add_le_add_right ih 1) All goals completed! 🐙) wThe 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