Source code on Github{-# OPTIONS --safe --without-K #-}
module Reflection.AntiUnification where
open import Meta.Prelude
open import Meta.Init
import Data.Maybe as Maybe
import Data.Nat as Nat
open import Data.Product
open import Reflection.AlphaEquality
open import Class.DecEq
module VarDescend (♯vars : ℕ) where
varDescend : ℕ → ℕ → ℕ
varDescend ϕ x = if ϕ Nat.≤ᵇ x then ♯vars + x else x
patternDescend : ℕ → Pattern → Pattern × ℕ
patternsDescend : ℕ → Args Pattern → Args Pattern × ℕ
patternDescend ϕ (con c ps) = map₁ (con c) (patternsDescend ϕ ps)
patternDescend ϕ (dot t) = dot t , ϕ
patternDescend ϕ (var x) = var (varDescend ϕ x) , suc ϕ
patternDescend ϕ (lit l) = lit l , ϕ
patternDescend ϕ (proj f) = proj f , ϕ
patternDescend ϕ (absurd x) = absurd (varDescend ϕ x) , suc ϕ
patternsDescend ϕ ((arg i p) ∷ ps) =
let (p' , ϕ') = patternDescend ϕ p
(ps' , ϕ'') = patternsDescend ϕ' ps
in (arg i p ∷ ps' , ϕ'')
patternsDescend ϕ [] =
[] , ϕ
module AntiUnification (cmp : Term → Term → ℕ) (♯vars : ℕ) where
open VarDescend ♯vars
antiUnify : ℕ → Term → Term → Term
antiUnifyArgs : ℕ → Args Term → Args Term → Maybe (Args Term)
antiUnifyClauses : ℕ → Clauses → Clauses → Maybe Clauses
antiUnifyClause : ℕ → Clause → Clause → Maybe Clause
antiUnify ϕ t@(var x args) t'@(var y args') with x ≡ᵇ y | antiUnifyArgs ϕ args args'
... | _ | nothing = var (cmp t t' + ϕ) []
... | false | just uargs = var (cmp t t' + ϕ) uargs
... | true | just uargs = var (varDescend ϕ x) uargs
antiUnify ϕ t@(con c args) t'@(con c' args') with c ≡ᵇ c' | antiUnifyArgs ϕ args args'
... | _ | nothing = var (cmp t t' + ϕ) []
... | false | just uargs = var (cmp t t' + ϕ) []
... | true | just uargs = con c uargs
antiUnify ϕ t@(def f args) t'@(def f' args') with f ≡ᵇ f' | antiUnifyArgs ϕ args args'
... | _ | nothing = var (cmp t t' + ϕ) []
... | false | just uargs = var (cmp t t' + ϕ) []
... | true | just uargs = def f uargs
antiUnify ϕ (lam v (abs s t)) (lam _ (abs _ t')) =
lam v (abs s (antiUnify (suc ϕ) t t'))
antiUnify ϕ t@(pat-lam cs args) t'@(pat-lam cs' args') with antiUnifyClauses ϕ cs cs' | antiUnifyArgs ϕ args args'
... | nothing | _ = var (cmp t t' + ϕ) []
... | _ | nothing = var (cmp t t' + ϕ) []
... | just ucs | just uargs = pat-lam ucs uargs
antiUnify ϕ (Π[ s ∶ arg i a ] b) (Π[ _ ∶ arg _ a' ] b') =
Π[ s ∶ arg i (antiUnify ϕ a a') ] antiUnify (suc ϕ) b b'
antiUnify ϕ (sort (set t)) (sort (set t')) =
sort (set (antiUnify ϕ t t'))
antiUnify ϕ t@(sort (lit n)) t'@(sort (lit n')) with n ≡ᵇ n'
... | true = sort (lit n)
... | false = var (cmp t t' + ϕ) []
antiUnify ϕ t@(sort (propLit n)) t'@(sort (propLit n')) with n ≡ᵇ n'
... | true = sort (propLit n)
... | false = var (cmp t t' + ϕ) []
antiUnify ϕ t@(sort (inf n)) t'@(sort (inf n')) with n ≡ᵇ n'
... | true = sort (inf n)
... | false = var (cmp t t' + ϕ) []
antiUnify ϕ (sort unknown) (sort unknown) =
sort unknown
antiUnify ϕ t@(lit l) t'@(lit l') with l == l'
... | true = lit l
... | false = var (cmp t t' + ϕ) []
antiUnify ϕ t@(meta x args) t'@(meta x' args') with x == x' | antiUnifyArgs ϕ args args'
... | _ | nothing = var (cmp t t' + ϕ) []
... | false | _ = var (cmp t t' + ϕ) []
... | true | just uargs = meta x uargs
antiUnify ϕ unknown unknown = unknown
antiUnify ϕ t@_ t'@_ = var (cmp t t' + ϕ) []
antiUnifyArgs ϕ (arg i t ∷ args) (arg _ t' ∷ args') =
Maybe.map (arg i (antiUnify ϕ t t') ∷_) (antiUnifyArgs ϕ args args')
antiUnifyArgs ϕ [] [] = just []
antiUnifyArgs ϕ _ _ = nothing
antiUnifyClause ϕ (clause Γ pats t) (clause Δ pats' t') =
Maybe.when ((Γ =α= Δ) ∧ (pats =α= pats'))
let (upats , ϕ') = patternsDescend ϕ pats
in clause Γ upats (antiUnify ϕ' t t')
antiUnifyClause ϕ (absurd-clause Γ pats) (absurd-clause Δ pats') =
Maybe.when ((Γ =α= Δ) ∧ (pats =α= pats')) $
absurd-clause Γ pats
antiUnifyClause ϕ _ _ =
nothing
antiUnifyClauses ϕ (c ∷ cs) (c' ∷ cs') =
Maybe.ap (Maybe.map _∷_ (antiUnifyClause ϕ c c')) (antiUnifyClauses ϕ cs cs')
antiUnifyClauses ϕ _ _ =
just []