\begin{code} {-# OPTIONS --experimental-lossy-unification --safe #-} open import Prelude renaming (tt to ⟨⟩) open import Signatures open import FinitenessConditions open import FreeMonad.PackagedTheory open import Data.String.Properties renaming (discreteChar to _≟_) module Effects.Parser.HElim (choiceString : SplitQuotientedChoiceω String) where open import Effects.Parser choiceString open import Effects.Parser.TreeParser choiceString open import Hoare.Definition ℙ-theory open import Hoare.Calculus ℙ-theory open import Hoare.Lemmas ℙ-theory open Signature (FullTheory.𝔽 ℙ-theory) open import Truth push-remaining : ∀ s → ⟅⟆ r ← (do r ← get; put (s ++ r); return r) ⟅ remaining (s ++ r) ⟆ push-remaining s = (λ r → put-remaining (s ++ r)) ⦂ (∀ r → ⟅⟆ _ ← put (s ++ r) ⟅ remaining (s ++ r) ⟆ ) ⇒⟨ seq ⟨return True ⟩ (const ⟨return True ⟩) (λ { (r , _) → ⟨remaining⟩ (s ++ r) }) (⟅→⟆True (return True) get) ⟩ ⟅⟆ (r , _) ← (get ;, (λ r → put (s ++ r))) ⟅ remaining (s ++ r) ⟆ ⇒⟨ focus fst ⟩ ⟅⟆ r ← fst <$> (get ;, (λ r → put (s ++ r))) ⟅ remaining (s ++ r) ⟆ ⇒⟨ subst-⟅⟆ (assoc get _ _) ⟩ ⟅⟆ r ← (do r ← get; put (s ++ r); return r) ⟅ remaining (s ++ r) ⟆ remaining-get : ∀ r → ⟅ remaining r ⟆ r′ ← get ⟅ return (r |≡| r′) ⟆ remaining-get r .proof k = (do a ← remaining r r′ ← get k r′ (a |→| (r |≡| r′))) ≡⟨ assoc get _ _ ⟩ (do r″ ← get r′ ← get k r′ ((r |≡| r″) |→| (r |≡| r′))) ≡⟨ get-get _ ⟩ (do r′ ← get k r′ ((r |≡| r′) |→| (r |≡| r′))) ≡⟨ r′ ⇐ get ;/ cong (k r′) (|→|-id _) ⟩ (do r′ ← get k r′ True) ≡˘⟨ get-nop (do r′ ← get; k r′ True) ⟩ (do _ ← get r′ ← get k r′ True) ≡˘⟨ assoc get _ _ ⟩ (do a ← remaining r r′ ← get k r′ True) ∎ parse-put-print : ∀ s (p : Term A) v → s ∈ p ↦ v → ⟅⟆ ((r , v′) , r′) ← (do r ← get; put (s ++ r); v′ ← p; r′ ← get; return ((r , v′) , r′)) ⟅ return ((r |≡| r′) |∧| (v |≡| v′)) ⟆ parse-put-print s p v s∈p↦v = s∈p↦v ⦂ s ∈ p ↦ v ⇒⟨⟩ (∀ r → ⟅ remaining (s ++ r) ⟆ v′ ← p ⟅ return (v |≡| v′) ⟨∧⟩ remaining r ⟆) ⇒⟨ seq ⟨return True ⟩ (λ r → ⟨remaining⟩ (s ++ r)) (λ { (r , v′) → return (v |≡| v′) ⟨∧⟩ remaining r , sef-<$> _ _ (sef-rem r) , det-<$> _ _ (det-rem r) } ) {p = (do r ← get; put (s ++ r); return r)} {q = const p} (push-remaining s) ⟩ ⟅⟆ (r , v′) ← ((do r ← get; put (s ++ r); return r) ⟪,⟫ p) ⟅ return (v |≡| v′) ⟨∧⟩ remaining r ⟆ ⇒⟨ subst-⟅⟆ (assoc get _ _) ⟩ ⟅⟆ (r , v′) ← (do r ← get; put (s ++ r); v′ ← p; return (r , v′)) ⟅ return (v |≡| v′) ⟨∧⟩ remaining r ⟆ ⇒⟨ ⟅∙⟆≡ (λ { (r , v′) → assoc get _ _ ; (r′ ⇐ get ;/ cong return (∧-com (v |≡| v′) (r |≡| r′)) ) ; sym (assoc get _ _) }) ⟩ ⟅⟆ (r , v′) ← (do r ← get; put (s ++ r); v′ ← p; return (r , v′)) ⟅ remaining r ⟨∧⟩ return (v |≡| v′) ⟆ ⇒⟨ flip (seq ⟨return True ⟩ (λ { (r , v′) → remaining r ⟨∧⟩ return (v |≡| v′) , sef-<$> _ _ (sef-rem r) , det-<$> _ _ (det-rem r) }) λ { ((r , v′) , r′) → ⟨return ((r |≡| r′) |∧| (v |≡| v′)) ⟩ }) ( λ { (r , v′) → ⟨&&&⟩ʳ (remaining r) (λ r′ → return (r |≡| r′)) (v |≡| v′) get (remaining-get r) }) ⟩ ⟅⟆ ((r , v′) , r′) ← (do r ← get; put (s ++ r); v′ ← p; return (r , v′)) ⟪,⟫ get ⟅ return ((r |≡| r′) |∧| (v |≡| v′)) ⟆ ⇒⟨ subst-⟅⟆ (assoc get _ _ ; r ⇐ get ;/ assoc (put (s ++ r)) (const (p >>= λ v′ → return (r , v′))) _ ; _ ⇐ put (s ++ r) ;/ assoc p (λ v′ → return (r , v′)) _) ⟩ ⟅⟆ ((r , v′) , r′) ← (do r ← get; put (s ++ r); v′ ← p; r′ ← get; return ((r , v′) , r′)) ⟅ return ((r |≡| r′) |∧| (v |≡| v′)) ⟆ open import FreeMonad.FindVars open import Finite open import Data.String.Properties open import FreeMonad.Modalities ℙ-theory open import FreeMonad.Syntax (FullTheory.𝔽 ℙ-theory) open import Data.Tree import Effects.NonDet as NDM open NDM.NonDet using (`<|>; `fail) import Effects.State as STM open STM.StateFunctor using (`get; `put) module _ {A : Type a} where Totalₛ : Syntax A → Type Totalₛ (op (inl `fail , _)) = ⊥ Totalₛ _ = ⊤ Total : Term A → Type a Total = □ₚ Totalₛ Total-nop : ∀ r t → Total t → (do t; put r) ≡ put r Total-nop r t (s , e , p) = cong (_>> put r) (sym e) ; elim-s (λ s → (p : □ₛₚ Totalₛ s) → [ s ] >> put r ≡ put r) (λ { (var x) _ → refl ; (op (inl `<|> , k) P⟨xs⟩) (p , ps) → cong₂ _<|>_ (P⟨xs⟩ false (ps false)) (P⟨xs⟩ true (ps true)) ; <|>-idem (put r) ; (op (inr (`put s) , k) P⟨xs⟩) (_ , ps) → [ op (inr (`put s) , k) ] >> put r ≡⟨ cong (_>> put r) (syntactic-bind k Op⟦ inr (`put s) ⟧) ⟩ (do put s; [ k ⟨⟩ ]) >> put r ≡⟨ assoc (put s) (λ _ → [ k ⟨⟩ ]) (λ _ → put r) ⟩ (do put s; [ k ⟨⟩ ]; put r) ≡⟨ _ ⇐ (put s) ;/ P⟨xs⟩ ⟨⟩ (ps ⟨⟩) ⟩ (do put s; put r) ≡⟨ put-put s r (return ⟨⟩) ⟩ put r ∎ ; (op (inr `get , k) P⟨xs⟩) (_ , ps) → [ op (inr `get , k) ] >> put r ≡⟨ cong (_>> put r) (syntactic-bind k Op⟦ inr `get ⟧) ⟩ (do s ← get; [ k s ]) >> put r ≡⟨ assoc get _ _ ⟩ (do s ← get; [ k s ]; put r) ≡⟨ s ⇐ get ;/ P⟨xs⟩ s (ps s) ⟩ (do s ← get; put r) ≡⟨ get-nop (put r) ⟩ put r ∎ }) s p module _ (fv : FindVars (FullTheory.𝒯 ℙ-theory)) (fa : ∀ O → ℰ (Arity O)) where open import Hoare.HElim ℙ-theory fv fa parse-equality : ∀ t n → (do s ← get; put (print t ++ s); t′ ← parse-tree n; s′ ← get; put s′; return t′) ≡ (do s ← get; put (print t ++ s); _ ← parse-tree n; s′ ← get; put s ; return t) parse-equality t n = let h = H-elim (λ { ((r , v′) , r′) → (r |≡| r′) |∧| (t |≡| v′) }) (λ { ((r , v′ ) , r′) → put r′ >> return v′ }) (λ { ((r , v′) , r′) → put r >> return t }) (λ { ((r , v′) , r′) (r≡r′ , t≡v′) → cong₂ (λ r v → put r >> return v) (∥rec∥ (isOfHLevelList 0 isSetChar _ _) sym r≡r′) (∥rec∥ (Discrete→isSet tree-eq _ _) sym t≡v′) }) _ (parse-put-print (print t) (parse-tree n) t (round-trip n t)) in sym ( assoc get _ _ ; r ⇐ get ;/ assoc (put (print t ++ r)) _ _ ; _ ⇐ put (print t ++ r) ;/ assoc (parse-tree n) _ _ ; v′ ⇐ parse-tree n ;/ assoc get _ _) ; h ; assoc get _ _ ; r ⇐ get ;/ assoc (put (print t ++ r)) _ _ ; _ ⇐ put (print t ++ r) ;/ assoc (parse-tree n) _ _ ; v′ ⇐ parse-tree n ;/ assoc get _ _ push-print-lhs : ∀ t n → (do s ← get; put (print t ++ s); t′ ← parse-tree n; s′ ← get; put s′; return t′) ≡ (do s ← get; put (print t ++ s); parse-tree n) push-print-lhs t n = s ⇐ get ;/ _ ⇐ put (print t ++ s) ;/ ((t′ ⇐ parse-tree n ;/ get-put (return t′))) ; >>=-idʳ (parse-tree n) push-print-rhs : ∀ t n → Total (do push (print t); parse-tree n) → (do s ← get; put (print t ++ s); _ ← parse-tree n; s′ ← get; put s ; return t) ≡ return t push-print-rhs t n tot = (do s ← get put (print t ++ s) _ ← parse-tree n s′ ← get put s return t) ≡⟨ s ⇐ get ;/ _ ⇐ put (print t ++ s) ;/ _ ⇐ parse-tree n ;/ get-nop (put s >> return t) ⟩ (do s ← get put (print t ++ s) _ ← parse-tree n put s return t) ≡˘⟨ get-get _ ⟩ (do s ← get s′ ← get put (print t ++ s′) _ ← parse-tree n put s return t) ≡˘⟨ s ⇐ get ;/ assoc (push (print t) >> parse-tree n) _ _ ; assoc (push (print t)) (const (parse-tree n)) (const (put s >> return t)) ; assoc get _ _ ⟩ (do s ← get ((push (print t) >> parse-tree n) >> put s) return t) ≡⟨ s ⇐ get ;/ cong (_>> return t) (Total-nop s (push (print t) >> parse-tree n) tot ) ⟩ (do s ← get put s return t) ≡⟨ get-put (return t) ⟩ return t ∎ push-print-parse : ∀ t n → Total (do push (print t); parse-tree n) → (do push (print t); parse-tree n) ≡ return t push-print-parse t n tot = assoc get _ _ ; sym (push-print-lhs t n) ; parse-equality t n ; push-print-rhs t n tot \end{code}