open import Data.Nat.Base using (_≤_; _<_; s<s; z≤n)
open import Data.Nat.Induction using (<-wellFounded)
open import Data.Nat.Properties using
(+-identityʳ; +-assoc; ≤-refl; module ≤-Reasoning; +-mono-≤; n≤1+n;
n<1+n; 0<1+n; +-mono-<-≤; +-mono-≤-<; m≤n⇒m<n∨m≡n; m≤m+n; m≤n+m)
open import Data.Product using (Σ-syntax; _×_; _,_; proj₁; proj₂)
open import Data.Product.Relation.Binary.Lex.Strict using (×-Lex; ×-wellFounded)
open import Data.Sum using (inj₁; inj₂)
open import Function.Base using (_on_)
open import Induction.WellFounded as WellFounded using (WellFounded; Acc; acc)
open import Relation.Binary.Construct.On using () renaming (wellFounded to on-wellFounded)
open import CoverageCheck.Prelude hiding (Σ-syntax; _×_; _,_; _<_)
open import CoverageCheck.GlobalScope using (Globals)
open import CoverageCheck.Instance
open import CoverageCheck.Subsumption
open import CoverageCheck.Syntax
open import CoverageCheck.Name
open import Data.Set as Set using (Set)
open import Haskell.Data.List.NonEmpty using (NonEmpty)
open import CoverageCheck.Usefulness.Algorithm.Types hiding (_,_,_)
open import CoverageCheck.Usefulness.Algorithm.Raw
open import CoverageCheck.Usefulness.Algorithm.MissingConstructors
module @0 CoverageCheck.Usefulness.Algorithm.Termination
⦃ globals : Globals ⦄
⦃ sig : Signature ⦄
where
private open module G = Globals globals
private
variable
α : Ty
αs βs : Tys
αss : TyStack
d : NameData
∥_∥ : Patterns αs → Nat → Nat
∥ [] ∥ n = n
∥ — ∷ ps ∥ n = ∥ ps ∥ n
∥ con c rs ∷ ps ∥ n = suc (∥ rs ∥ (∥ ps ∥ n))
∥ r₁ ∣ r₂ ∷ ps ∥ n = suc (∥ r₁ ∷ ps ∥ n + ∥ r₂ ∷ ps ∥ n)
∥_∥ˢ' : PatternStack αss → Nat → Nat
∥ [] ∥ˢ' n = n
∥ ps ∷ pss ∥ˢ' n = ∥ ps ∥ (∥ pss ∥ˢ' n)
∥_∥ˢ : PatternStack αss → Nat
∥ pss ∥ˢ = ∥ pss ∥ˢ' 0
∥_∥ˢᵐ : PatternStackMatrix αss → Nat
∥ psmat ∥ˢᵐ = sum (map ∥_∥ˢ psmat)
∥_∥ᵗ : TyStack → Nat
∥ [] ∥ᵗ = 0
∥ αs ∷ αss ∥ᵗ = suc (lengthNat αs + ∥ αss ∥ᵗ)
Input : Type
Input = Σ[ αss ∈ _ ] PatternStackMatrix αss × PatternStack αss
inputSize : Input → Nat × Nat × Nat
inputSize (αss , psmat , ps) = ∥ psmat ∥ˢᵐ , ∥ ps ∥ˢ , ∥ αss ∥ᵗ
_⊏_ : Input → Input → Type
_⊏_ = ×-Lex _≡_ _<_ (×-Lex _≡_ _<_ _<_) on inputSize
⊏-wellFounded : WellFounded _⊏_
⊏-wellFounded =
on-wellFounded inputSize
(×-wellFounded <-wellFounded (×-wellFounded <-wellFounded <-wellFounded))
open WellFounded.All ⊏-wellFounded renaming (wfRec to ⊏-rec)
pattern ↓₀ ∣P∣<∣Q∣ = inj₁ ∣P∣<∣Q∣
pattern ↓₁ ∣P∣≡∣Q∣ ∣ps∣<∣qs∣ = inj₂ (∣P∣≡∣Q∣ , inj₁ ∣ps∣<∣qs∣)
pattern ↓₂ ∣P∣≡∣Q∣ ∣ps∣≡∣qs∣ ∣αss∣<∣βss∣ = inj₂ (∣P∣≡∣Q∣ , inj₂ (∣ps∣≡∣qs∣ , ∣αss∣<∣βss∣))
∥—*∥ : ∀ αs n → ∥ —* {αs} ∥ n ≡ n
∥—*∥ [] n = refl
∥—*∥ (α ∷ αs) n = ∥—*∥ αs n
sum-++ : (xs ys : List Nat) → sum (xs ++ ys) ≡ sum xs + sum ys
sum-++ [] ys = refl
sum-++ (x ∷ xs) ys rewrite sum-++ xs ys = sym (+-assoc x (sum xs) (sum ys))
∥∥-++ : (psmat psmat' : PatternStackMatrix αss)
→ ∥ psmat ++ psmat' ∥ˢᵐ ≡ ∥ psmat ∥ˢᵐ + ∥ psmat' ∥ˢᵐ
∥∥-++ psmat psmat'
rewrite map-++ ∥_∥ˢ psmat psmat' | sum-++ (map ∥_∥ˢ psmat) (map ∥_∥ˢ psmat')
= refl
∥∥-tail : (psmat : PatternStackMatrix ([] ∷ αss))
→ ∥ map tailAll psmat ∥ˢᵐ ≡ ∥ psmat ∥ˢᵐ
∥∥-tail [] = refl
∥∥-tail (([] ∷ pss) ∷ psmat) = cong (_ +_) (∥∥-tail psmat)
specialize'-≤ : (c : NameCon d) (pss : PatternStack ((TyData d ∷ αs) ∷ αss))
→ ∥ specialize' c pss ∥ˢᵐ ≤ ∥ pss ∥ˢ
specialize'-≤ {d0} c ((— ∷ ps) ∷ pss)
rewrite ∥—*∥ (argsTy (dataDefs sig d0) c) ∥ ps ∷ pss ∥ˢ
| +-identityʳ ∥ ps ∷ pss ∥ˢ
= ≤-refl
specialize'-≤ c ((con c' rs ∷ ps) ∷ pss) = lem (c ≟ c')
where
lem : (eq : Dec (c ≡ c'))
→ ∥ specializeConCase c rs ps pss eq ∥ˢᵐ
≤ suc ∥ rs ∷ ps ∷ pss ∥ˢ
lem (False ⟨ _ ⟩) = z≤n
lem (True ⟨ refl ⟩)
rewrite +-identityʳ ∥ rs ∷ ps ∷ pss ∥ˢ
= n≤1+n ∥ rs ∷ ps ∷ pss ∥ˢ
specialize'-≤ c ((r₁ ∣ r₂ ∷ ps) ∷ pss) =
begin
∥ specialize' c ((r₁ ∷ ps) ∷ pss) ++ specialize' c ((r₂ ∷ ps) ∷ pss) ∥ˢᵐ
≡⟨ ∥∥-++ (specialize' c ((r₁ ∷ ps) ∷ pss)) (specialize' c ((r₂ ∷ ps) ∷ pss)) ⟩
∥ specialize' c ((r₁ ∷ ps) ∷ pss) ∥ˢᵐ + ∥ specialize' c ((r₂ ∷ ps) ∷ pss) ∥ˢᵐ
≤⟨ +-mono-≤ (specialize'-≤ c ((r₁ ∷ ps) ∷ pss)) (specialize'-≤ c ((r₂ ∷ ps) ∷ pss)) ⟩
∥ (r₁ ∷ ps) ∷ pss ∥ˢ + ∥ (r₂ ∷ ps) ∷ pss ∥ˢ
<⟨ n<1+n _ ⟩
suc (∥ (r₁ ∷ ps) ∷ pss ∥ˢ + ∥ (r₂ ∷ ps) ∷ pss ∥ˢ)
∎
where open ≤-Reasoning
specialize-≤
: (c : NameCon d) (psmat : PatternStackMatrix ((TyData d ∷ αs) ∷ αss))
→ ∥ specialize c psmat ∥ˢᵐ ≤ ∥ psmat ∥ˢᵐ
specialize-≤ c [] = ≤-refl
specialize-≤ c (ps ∷ psmat) rewrite ∥∥-++ (specialize' c ps) (specialize c psmat)
= +-mono-≤ (specialize'-≤ c ps) (specialize-≤ c psmat)
specialize'-< : (c : NameCon d) (pss : PatternStack ((TyData d ∷ αs) ∷ αss))
→ c ∈ˢ pss
→ ∥ specialize' c pss ∥ˢᵐ < ∥ pss ∥ˢ
specialize'-< c ((con c' rs ∷ ps) ∷ pss) c≡c' = lem (c ≟ c')
where
lem : (eq : Dec (c ≡ c'))
→ ∥ specializeConCase c rs ps pss eq ∥ˢᵐ
< suc ∥ rs ∷ ps ∷ pss ∥ˢ
lem (False ⟨ c≢c' ⟩) = contradiction c≡c' c≢c'
lem (True ⟨ refl ⟩)
rewrite +-identityʳ ∥ rs ∷ ps ∷ pss ∥ˢ
= ≤-refl
specialize'-< c ((r₁ ∣ r₂ ∷ ps) ∷ pss) (Left h) =
begin
suc ∥ specialize' c ((r₁ ∷ ps) ∷ pss) ++ specialize' c ((r₂ ∷ ps) ∷ pss) ∥ˢᵐ
≡⟨ cong suc (∥∥-++ (specialize' c ((r₁ ∷ ps) ∷ pss)) (specialize' c ((r₂ ∷ ps) ∷ pss))) ⟩
suc (∥ specialize' c ((r₁ ∷ ps) ∷ pss) ∥ˢᵐ + ∥ specialize' c ((r₂ ∷ ps) ∷ pss) ∥ˢᵐ)
<⟨ s<s (+-mono-<-≤ (specialize'-< c ((r₁ ∷ ps) ∷ pss) h) (specialize'-≤ c ((r₂ ∷ ps) ∷ pss))) ⟩
suc (∥ (r₁ ∷ ps) ∷ pss ∥ˢ + ∥ (r₂ ∷ ps) ∷ pss ∥ˢ)
∎
where open ≤-Reasoning
specialize'-< c ((r₁ ∣ r₂ ∷ ps) ∷ pss) (Right h) =
begin
suc ∥ specialize' c ((r₁ ∷ ps) ∷ pss) ++ specialize' c ((r₂ ∷ ps) ∷ pss) ∥ˢᵐ
≡⟨ cong suc (∥∥-++ (specialize' c ((r₁ ∷ ps) ∷ pss)) (specialize' c ((r₂ ∷ ps) ∷ pss))) ⟩
suc (∥ specialize' c ((r₁ ∷ ps) ∷ pss) ∥ˢᵐ + ∥ specialize' c ((r₂ ∷ ps) ∷ pss) ∥ˢᵐ)
<⟨ s<s (+-mono-≤-< (specialize'-≤ c ((r₁ ∷ ps) ∷ pss)) (specialize'-< c ((r₂ ∷ ps) ∷ pss) h)) ⟩
suc (∥ (r₁ ∷ ps) ∷ pss ∥ˢ + ∥ (r₂ ∷ ps) ∷ pss ∥ˢ)
∎
where open ≤-Reasoning
specialize-< : (c : NameCon d) (psmat : PatternStackMatrix ((TyData d ∷ αs) ∷ αss))
→ c ∈ˢᵐ psmat
→ ∥ specialize c psmat ∥ˢᵐ < ∥ psmat ∥ˢᵐ
specialize-< c (pss ∷ psmat) (here h)
rewrite ∥∥-++ (specialize' c pss) (specialize c psmat)
= +-mono-<-≤ (specialize'-< c pss h) (specialize-≤ c psmat)
specialize-< c (pss ∷ psmat) (there h)
rewrite ∥∥-++ (specialize' c pss) (specialize c psmat)
= +-mono-≤-< (specialize'-≤ c pss) (specialize-< c psmat h)
default'-≤ : (pss : PatternStack ((TyData d ∷ αs) ∷ αss))
→ ∥ default' pss ∥ˢᵐ ≤ ∥ pss ∥ˢ
default'-≤ ((— ∷ ps) ∷ pss)
rewrite +-identityʳ ∥ ps ∷ pss ∥ˢ
= ≤-refl
default'-≤ ((con _ _ ∷ ps) ∷ pss) = z≤n
default'-≤ ((r₁ ∣ r₂ ∷ ps) ∷ pss) =
begin
∥ default' ((r₁ ∷ ps) ∷ pss) ++ default' ((r₂ ∷ ps) ∷ pss) ∥ˢᵐ
≡⟨ ∥∥-++ (default' ((r₁ ∷ ps) ∷ pss)) (default' ((r₂ ∷ ps) ∷ pss)) ⟩
∥ default' ((r₁ ∷ ps) ∷ pss) ∥ˢᵐ + ∥ default' ((r₂ ∷ ps) ∷ pss) ∥ˢᵐ
≤⟨ +-mono-≤ (default'-≤ ((r₁ ∷ ps) ∷ pss)) (default'-≤ ((r₂ ∷ ps) ∷ pss)) ⟩
∥ (r₁ ∷ ps) ∷ pss ∥ˢ + ∥ (r₂ ∷ ps) ∷ pss ∥ˢ
<⟨ n<1+n _ ⟩
suc (∥ (r₁ ∷ ps) ∷ pss ∥ˢ + ∥ (r₂ ∷ ps) ∷ pss ∥ˢ)
∎
where open ≤-Reasoning
default-≤ : (psmat : PatternStackMatrix ((TyData d ∷ αs) ∷ αss))
→ ∥ default_ psmat ∥ˢᵐ ≤ ∥ psmat ∥ˢᵐ
default-≤ [] = ≤-refl
default-≤ (ps ∷ psmat) rewrite ∥∥-++ (default' ps) (default_ psmat)
= +-mono-≤ (default'-≤ ps) (default-≤ psmat)
tail-⊏ : (psmat : PatternStackMatrix ([] ∷ αss)) (pss : PatternStack αss)
→ (_ , map tailAll psmat , pss) ⊏ (_ , psmat , [] ∷ pss)
tail-⊏ psmat pss = ↓₂ (∥∥-tail psmat) refl (n<1+n _)
specializeCon-⊏ : (psmat : PatternStackMatrix ((TyData d ∷ αs) ∷ αss))
→ (c : NameCon d) (rs : Patterns (argsTy (dataDefs sig d) c))
→ (ps : Patterns αs) (pss : PatternStack αss)
→ (_ , specialize c psmat , rs ∷ ps ∷ pss) ⊏ (_ , psmat , (con c rs ∷ ps) ∷ pss)
specializeCon-⊏ psmat c rs ps pss with m≤n⇒m<n∨m≡n (specialize-≤ c psmat)
... | inj₁ ∣specPsmat∣<∣psmat∣ = ↓₀ ∣specPsmat∣<∣psmat∣
... | inj₂ ∣specPsmat∣≡∣psmat∣ = ↓₁ ∣specPsmat∣≡∣psmat∣ (n<1+n _)
default-⊏ : (psmat : PatternStackMatrix ((TyData d ∷ αs) ∷ αss))
→ (qs : Patterns αs) (pss : PatternStack αss)
→ (_ , default_ psmat , qs ∷ pss) ⊏ (_ , psmat , (— ∷ qs) ∷ pss)
default-⊏ psmat qs pss with m≤n⇒m<n∨m≡n (default-≤ psmat)
... | inj₁ ∣defPsmat∣<∣psmat∣ = ↓₀ ∣defPsmat∣<∣psmat∣
... | inj₂ ∣defPsmat∣≡∣psmat∣ = ↓₂ ∣defPsmat∣≡∣psmat∣ refl (n<1+n _)
specializeWild-⊏
: (c : NameCon d) (psmat : PatternStackMatrix ((TyData d ∷ αs) ∷ αss))
→ (qs : Patterns αs) (pss : PatternStack αss)
→ c ∈ˢᵐ psmat
→ (_ , specialize c psmat , —* ∷ qs ∷ pss) ⊏ (_ , psmat , (— ∷ qs) ∷ pss)
specializeWild-⊏ {d0} c psmat qs pss h
rewrite ∥—*∥ (argsTy (dataDefs sig d0) c) ∥ qs ∷ pss ∥ˢ
= ↓₀ (specialize-< c psmat h)
or-⊏ₗ : (psmat : PatternStackMatrix ((α ∷ αs) ∷ αss))
→ (r₁ r₂ : Pattern α) (ps : Patterns αs) (pss : PatternStack αss)
→ (_ , psmat , (r₁ ∷ ps) ∷ pss) ⊏ (_ , psmat , ((r₁ ∣ r₂) ∷ ps) ∷ pss)
or-⊏ₗ psmat r₁ r₂ ps pss =
↓₁ refl (m≤m+n _ ∥ (r₂ ∷ ps) ∷ pss ∥ˢ)
or-⊏ᵣ : (psmat : PatternStackMatrix ((α ∷ αs) ∷ αss))
→ (r₁ r₂ : Pattern α) (ps : Patterns αs) (pss : PatternStack αss)
→ (_ , psmat , (r₂ ∷ ps) ∷ pss) ⊏ (_ , psmat , ((r₁ ∣ r₂) ∷ ps) ∷ pss)
or-⊏ᵣ psmat r₁ r₂ ps pss =
↓₁ refl (s<s (m≤n+m _ ∥ (r₁ ∷ ps) ∷ pss ∥ˢ))
data UsefulAcc : (psmat : PatternStackMatrix αss) (ps : PatternStack αss) → Type where
done : {psmat : PatternStackMatrix []} → UsefulAcc psmat []
tailStep : {psmat : PatternStackMatrix ([] ∷ αss)} {pss : PatternStack αss}
→ UsefulAcc (map tailAll psmat) pss
→ UsefulAcc psmat ([] ∷ pss)
wildStep : {psmat : PatternStackMatrix ((TyData d ∷ αs) ∷ αss)}
→ {ps : Patterns αs} {pss : PatternStack αss}
→ UsefulAcc (default_ psmat) (ps ∷ pss)
→ (∀ c → c ∈ˢᵐ psmat → UsefulAcc (specialize c psmat) (—* ∷ ps ∷ pss))
→ UsefulAcc psmat ((— ∷ ps) ∷ pss)
conStep : {psmat : PatternStackMatrix ((TyData d ∷ βs) ∷ αss)} {c : NameCon d}
→ (let αs = argsTy (dataDefs sig d) c)
→ {rs : Patterns αs} {ps : Patterns βs} {pss : PatternStack αss}
→ UsefulAcc (specialize c psmat) (rs ∷ ps ∷ pss)
→ UsefulAcc psmat ((con c rs ∷ ps) ∷ pss)
orStep : {psmat : PatternStackMatrix ((α ∷ αs) ∷ αss)}
→ {r₁ r₂ : Pattern α} {ps : Patterns αs} {pss : PatternStack αss}
→ UsefulAcc psmat ((r₁ ∷ ps) ∷ pss)
→ UsefulAcc psmat ((r₂ ∷ ps) ∷ pss)
→ UsefulAcc psmat ((r₁ ∣ r₂ ∷ ps) ∷ pss)
∀UsefulAcc : (psmat : PatternStackMatrix αss) (ps : PatternStack αss)
→ UsefulAcc psmat ps
∀UsefulAcc psmat ps =
⊏-rec _ (λ (_ , psmat , ps) → UsefulAcc psmat ps)
(λ where
(αss , psmat , []) rec → done
(αss , psmat , [] ∷ pss) rec →
tailStep (rec (tail-⊏ psmat pss))
(αss , psmat , (con c rs ∷ ps) ∷ pss) rec →
conStep (rec (specializeCon-⊏ psmat c rs ps pss))
(αss , psmat , (r₁ ∣ r₂ ∷ ps) ∷ pss) rec →
orStep
(rec (or-⊏ₗ psmat r₁ r₂ ps pss))
(rec (or-⊏ᵣ psmat r₁ r₂ ps pss))
((TyData d ∷ αs) ∷ αss , psmat , (— ∷ ps) ∷ pss) rec →
wildStep
(rec (default-⊏ psmat ps pss))
(λ c h → rec (specializeWild-⊏ c psmat ps pss h)))
(_ , psmat , ps)