Research source · Plain text

Example.lean

site/public/formal/persistent-stacks/lean/FPRDTransfer/Example.lean

98 lines. Source is displayed for inspection; it is not executed by this page.

File fingerprint

SHA-256: e39bc1915e41b4176bcb3db3c6c8873e3923d173e066d1fc964901ea1ea970c3

/-
Executable non-vacuity checks.

The theorems in this development are universally quantified, so they would also
hold of a degenerate model in which nothing ever happens.  These examples run
the *published* LMR machinery -- `Scaffold.append`, path-named targets, the
tree unfolding -- on concrete inputs and check the decoded result against a
hand-computed answer, so a degenerate definition would be visible here.

Everything is closed by `decide` or `rfl`, i.e. by kernel computation.
-/

import FPRDTransfer.RealtimeTransfer

namespace FPRD
namespace Examples

/-! ### A one-stack machine that records its input -/

/-- Push every input symbol onto the single stack. -/
def recorder : StackMachine Bool Unit Bool 1 where
  step := fun _ x _ => ((), fun _ => .push x)
  init := ()
  accept := fun _ => true

/-- The stack holds the input reversed, top first. -/
example : (recorder.run [true, false, false]).stacks 0 = [false, false, true] := by decide

/-- The compiled scaffolding automaton appends one node per input symbol. -/
example : ((compile recorder).run [true, false, false]).2.top = 3 := by decide

/-- Decoding the compiled scaffold reproduces the stack.  This exercises
`Scaffold.append`, target resolution by port word, and `decode`. -/
example :
    decode ((compile recorder).run [true, false, false]).2 0
      ((compile recorder).run [true, false, false]).2.top = [false, false, true] := by
  rw [decode_eq_decodeAux]; decide

/-! ### A one-stack machine that pops -/

/-- Push on `true`, pop on `false`.  Exercises the `pop` port word `[j, j]`,
including popping the empty stack. -/
def pusher : StackMachine Bool Unit Bool 1 where
  step := fun _ x _ => ((), fun _ => if x then .push true else .pop)
  init := ()
  accept := fun _ => true

/-- Popping an empty stack is a no-op, and the encoding agrees.  This is the
case `CleanEmpty` exists to protect: the first `false` pops an empty stack. -/
example : (pusher.run [false, true, true, false]).stacks 0 = [true] := by decide

example :
    decode ((compile pusher).run [false, true, true, false]).2 0
      ((compile pusher).run [false, true, true, false]).2.top = [true] := by
  rw [decode_eq_decodeAux]; decide

/-- A longer alternation through three consecutive empty-stack pops.  The
generated empty tops have missing same-stack ports; the example checks the
decoded result without claiming that this run realizes the more general stale
history excluded by `CleanEmpty`. -/
example :
    decode ((compile pusher).run [true, false, false, false, true]).2 0
      ((compile pusher).run [true, false, false, false, true]).2.top = [true] := by
  rw [decode_eq_decodeAux]; decide

/-! ### A one-tape machine through the zipper -/

/-- Write the input symbol and move right, forever. -/
def copier : MultiTapeMachine Bool Unit (Option Bool) 1 where
  blank := none
  step := fun _ x _ => ((), fun _ => (some x, .right))
  init := ()
  accept := fun _ => true

/-- The tape's left half is the input reversed; the head sits on a blank. -/
example : ((copier.run [true, false, true]).tapes 0).left
    = [some true, some false, some true] := by decide

example : ((copier.run [true, false, true]).tapes 0).cur = none := by decide

/-- The scaffold compiled through the zipper decodes to the same tape half.
Degree is `2 * 1 = 2`, distance `2`, three nodes for three symbols. -/
example :
    decode ((compile copier.toStack).run [true, false, true]).2 (leftIdx 0)
      ((compile copier.toStack).run [true, false, true]).2.top
      = [some true, some false, some true] := by
  rw [decode_eq_decodeAux]; decide

example : ((compile copier.toStack).run [true, false, true]).2.top = 3 := by decide

/-- The right half stays empty: a blank is read there, not a recorded cell. -/
example :
    decode ((compile copier.toStack).run [true, false, true]).2 (rightIdx 0)
      ((compile copier.toStack).run [true, false, true]).2.top = [] := by
  rw [decode_eq_decodeAux]; decide

end Examples
end FPRD