Problem: stack_pop

Your task is to implement a Stack data structure and verify its Last-In, First-Out behavior in Lean. The stack is modeled as a mathematical sequence. Specifically, you are required to implement and verify the pop operation. Pop: You must prove that the operation returns the last element of the sequence and that the resulting model sequence is the original sequence minus its last element. You must also verify the safety precondition that the stack is non-empty before a pop. In a functional setting, the function should accept a proof of non-emptiness and return both the popped value and the new stack state.


import Mathlib

structure VerifiableStack (T : Type) where
  data : List T

def VerifiableStack.view {T} (s : VerifiableStack T) : List T :=
  s.data

def VerifiableStack.is_valid {T} (s : VerifiableStack T) : Prop :=
  True

-- Precondition definitions
@[reducible, simp]
def pop_precond {T} (s : VerifiableStack T) : Prop :=
  -- !benchmark @start precond
  s.is_valid ∧ s.view.length > 0
  -- !benchmark @end precond

-- !benchmark @start auxcode
-- !benchmark @end auxcode

-- Main function definition
-- Returns the projected pair (val, new_stack)
def pop {T} (s : VerifiableStack T)
    (h_precond : pop_precond s) : T × VerifiableStack T :=
  -- !benchmark @start code
  sorry
  -- !benchmark @end code

-- Postcondition definitions
@[reducible, simp]
def pop_postcond {T} (s : VerifiableStack T) (result : T × VerifiableStack T)
    (_ : pop_precond s) : Prop := -- We don't even need the proof term 'h' here!
  -- !benchmark @start postcond
  let (val, new_stack) := result
  new_stack.is_valid ∧
  -- Concise & Idiomatic: The old stack was the new stack followed by the popped value.
  s.view = new_stack.view ++ [val]
  -- !benchmark @end postcond

-- !benchmark @start lemma
-- !benchmark @end lemma

-- Proof content
theorem pop_postcond_satisfied {T} (s : VerifiableStack T)
    (h_precond : pop_precond s) :
    pop_postcond s (pop s h_precond) h_precond := by
  -- !benchmark @start proof
  sorry
  -- !benchmark @end proof