module Free-variables.Remove-substs where
open import Equality.Propositional
open import Prelude hiding (const)
open import Tactic.By.Propositional using (make-cong)
open import List equality-with-J as L
open import Monad equality-with-J
open import TC-monad equality-with-J hiding (Type)
open import Atom
import Chi
import Coding
open import Coding.Instances.Nat
open Chi χ-ℕ-atoms hiding (∷_)
open Coding χ-ℕ-atoms
open import Free-variables χ-ℕ-atoms
open import Reasoning χ-ℕ-atoms
open import Values χ-ℕ-atoms
private variable
a : Level
A : Type a
e e′ e″ e₁ e₂ : Exp
x y : A
private
subst-cong₁ : ∀ x e → e₁ ≡ e₂ → e₁ [ x ← e ] ≡ e₂ [ x ← e ]
subst-cong₁ _ _ = cong _[ _ ← _ ]
proof : List (Name × Term) → List (ℕ × Term) → Term → TC Term
proof closed-defs closed-vars t = the-proof ⟨$⟩ term t
where
data RHS : Type where
rep-rhs : Term → RHS
closed-rhs : Term → RHS
data Proof : Type where
trivial : Proof
non-trivial : Term → Maybe RHS → Proof
the-proof : Proof → Term
the-proof trivial = con (quote refl) []
the-proof (non-trivial p _) = p
mutual
term : Term → TC Proof
term (def (quote _[_←_])
(varg (def (quote Coding.Rep.⌜_⌝)
(_ ∷ _ ∷ _ ∷ _ ∷ _ ∷ _ ∷ varg e₁ ∷ [])) ∷
varg _ ∷ varg _ ∷ [])) =
subst-rep-proof e₁
term (def (quote Chi._[_←_])
(_ ∷ varg (def (quote Coding.Rep.⌜_⌝)
(_ ∷ _ ∷ _ ∷ _ ∷ _ ∷ _ ∷ varg e₁ ∷ [])) ∷
varg _ ∷ varg _ ∷ [])) =
subst-rep-proof e₁
term (def f@(quote _[_←_])
(varg e₁@(def (quote _[_←_]) _) ∷
varg x ∷ varg e₂ ∷ [])) =
subst-subst-proof f e₁ x e₂
term (def f@(quote Chi._[_←_])
(_ ∷ varg e₁@(def (quote _[_←_]) _) ∷
varg x ∷ varg e₂ ∷ [])) =
subst-subst-proof f e₁ x e₂
term (def f@(quote _[_←_])
(varg e₁@(def (quote Chi._[_←_]) _) ∷
varg x ∷ varg e₂ ∷ [])) =
subst-subst-proof f e₁ x e₂
term (def f@(quote Chi._[_←_])
(_ ∷ varg e₁@(def (quote Chi._[_←_]) _) ∷
varg x ∷ varg e₂ ∷ [])) =
subst-subst-proof f e₁ x e₂
term (def (quote _[_←_])
(varg (def e₁ []) ∷ varg x ∷ varg e₂ ∷ [])) =
subst-def-proof e₁ x e₂
term (def (quote Chi._[_←_])
(_ ∷ varg (def e₁ []) ∷ varg x ∷ varg e₂ ∷ [])) =
subst-def-proof e₁ x e₂
term (def (quote _[_←_])
(varg (var x₁ []) ∷ varg x ∷ varg e₂ ∷ [])) =
subst-var-proof x₁ x e₂
term (def (quote Chi._[_←_])
(_ ∷ varg (var x₁ []) ∷ varg x ∷ varg e₂ ∷ [])) =
subst-var-proof x₁ x e₂
term (con c ts) = try-cong (con c []) ts
term (def f ts) = try-cong (def f []) ts
term (var x ts) = try-cong (var x []) ts
term (meta m _) = blockOnMeta m
term _ = return trivial
subst-rep-proof : Term → TC Proof
subst-rep-proof e₁ = return $
non-trivial
(def (quote subst-rep) (varg e₁ ∷ []))
(just (rep-rhs e₁))
subst-subst-proof :
Name → Term → Term → Term → TC Proof
subst-subst-proof f e₁ x e₂ = do
p₁ ← term e₁
return $ case p₁ of λ where
trivial → trivial
(non-trivial p₁ e₁) → flip non-trivial e₁ $
let p₁ = def (quote subst-cong₁)
(varg x ∷ varg e₂ ∷ varg p₁ ∷ [])
in case e₁ of λ where
nothing → p₁
(just (rep-rhs e₁)) →
def (quote trans)
(varg p₁ ∷
varg (def (quote subst-rep) (varg e₁ ∷ [])) ∷
[])
(just (closed-rhs cl)) →
def (quote trans)
(varg p₁ ∷
varg (def (quote subst-closed)
(varg x ∷ varg e₂ ∷ varg cl ∷ [])) ∷
[])
subst-def-proof : Name → Term → Term → TC Proof
subst-def-proof e₁ x e₂ =
return $ case lookup eq-Name e₁ closed-defs of λ where
nothing → trivial
(just cl) → non-trivial
(def (quote subst-closed) (varg x ∷ varg e₂ ∷ varg cl ∷ []))
(just (closed-rhs cl))
subst-var-proof : ℕ → Term → Term → TC Proof
subst-var-proof x₁ x e₂ =
return $ case lookup eq-ℕ x₁ closed-vars of λ where
nothing → trivial
(just cl) → non-trivial
(def (quote subst-closed) (varg x ∷ varg e₂ ∷ varg cl ∷ []))
(just (closed-rhs cl))
try-cong : Term → List (Arg Term) → TC Proof
try-cong f [] =
return trivial
try-cong f ts =
case non-default-modality-after-first-visible-arg of λ where
true → return trivial
false → do
(ts , triv) ← args ts
case triv of λ where
true → return trivial
false → do
cong-proof ← make-cong visible-args
return
(non-trivial (def cong-proof (varg f ∷ ts)) nothing)
where
non-default-modality-after-first-visible-arg =
skip-prefix ts
where
skip-prefix : List (Arg Term) → Bool
skip-prefix ts@(arg (arg-info visible _) _ ∷ _) =
foldr _∨_ false $
flip L.map ts λ where
(arg (arg-info v m) _) →
not (eq-Modality m (modality relevant quantity-ω))
skip-prefix (_ ∷ ts) = skip-prefix ts
skip-prefix [] = true
visible-args = length $ flip filter ts λ where
(arg (arg-info v _) _) → eq-Visibility v visible
args : List (Arg Term) → TC (List (Arg Term) × Bool)
args [] =
return ([] , true)
args (arg i@(arg-info visible _) t ∷ ts) = do
p ← term t
(ps , triv) ← args ts
return $ (arg i (the-proof p) ∷ ps ,_) $
case p , triv of λ where
(trivial , true) → true
_ → false
args (_ ∷ ts) =
args ts
process-closed :
List (∃ λ (e : Exp) → Closed e) →
TC (List (Name × Term) × List (ℕ × Term))
process-closed [] = return ([] , [])
process-closed ((e , c) ∷ rest) = do
e ← quoteTC e
c ← quoteTC c
case e of λ where
(def f []) → Σ-map ((f , c) ∷_) id ⟨$⟩ process-closed rest
(var x []) → Σ-map id ((x , c) ∷_) ⟨$⟩ process-closed rest
_ → typeError $
termErr e ∷
strErr " is not the name of a definition or variable" ∷ []
remove-substs-tactic : List (∃ λ (e : Exp) → Closed e) → Term → TC ⊤
remove-substs-tactic closed goal =
inferType goal >>= reduce >>= λ where
(def (quote _≡_) (_ ∷ _ ∷ arg _ e ∷ _ ∷ [])) → do
closed-defs , closed-vars ← process-closed closed
t ← proof closed-defs closed-vars e
debugPrint "remove-substs" 5 $
strErr "The macro remove-substs constructed the following " ∷
strErr "proof term:\n" ∷
strErr " " ∷ termErr t ∷ []
unify goal t
_ → typeError $
termErr goal ∷ strErr " is not an equality type" ∷ []
macro
remove-substs :
List (∃ λ (e : Exp) → Closed e) → Term → TC ⊤
remove-substs closed goal = remove-substs-tactic closed goal
private
_ : Exp.rec 0 (var 0) ≡ rec 0 (var 0)
_ = remove-substs []
_ : Exp.const 12 (⌜ e ⌝ [ x ← e′ ] ∷ []) ≡ Exp.const 12 (⌜ e ⌝ ∷ [])
_ = remove-substs []
_ : Exp.const 12 (⌜ e ⌝ [ x ← e′ ] [ y ← e″ ] ∷ []) ≡
Exp.const 12 (⌜ e ⌝ ∷ [])
_ = remove-substs []
[id] : Exp
[id] = lambda 0 (var 0)
[id]-is-closed : Closed [id]
[id]-is-closed = from-⊎ $ closed? [id]
_ : Exp.const 12 ([id] [ x ← e′ ] ∷ []) ≡ Exp.const 12 ([id] ∷ [])
_ = remove-substs (([id] , [id]-is-closed) ∷ [])
_ : Exp.const 12 ([id] [ x ← e′ ] [ y ← e″ ] ∷ []) ≡
Exp.const 12 ([id] ∷ [])
_ = remove-substs (([id] , [id]-is-closed) ∷ [])
_ : (e : Exp) (cl : Closed e) →
Exp.const 12 (e [ x ← e′ ] [ y ← e″ ] ∷ []) ≡
Exp.const 12 (e ∷ [])
_ = λ e cl → remove-substs ((e , cl) ∷ [])
_ : (n : ℕ) → const 3 (⌜ n ⌝ ∷ []) ⇓ const 3 (⌜ n ⌝ ∷ [])
_ = λ n →
const 3 (⌜ n ⌝ ∷ []) ≡⟨ sym $ remove-substs [] ⟩⟶
const 3 (⌜ n ⌝ [ 0 ← const 0 [] ] ∷ []) ≡⟨ remove-substs [] ⟩⟶
const 3 (⌜ n ⌝ ∷ []) ■⟨ const _ (rep-value n ∷ []) ⟩
f : Exp → Exp
f e = const 7 (e ∷ [])
_ : f (⌜ e ⌝ [ x ← e′ ]) ≡ f ⌜ e ⌝
_ = remove-substs []
_ : (f : (n : ℕ) → ∃ λ (m : ℕ) → m ≡ n) (n : ℕ) →
Exp.const (proj₁ (f n)) (⌜ e ⌝ [ x ← e′ ] ∷ []) ≡
const (proj₁ (f n)) (⌜ e ⌝ ∷ [])
_ = λ _ _ → remove-substs []