Source code on Github
{-# OPTIONS -v rewrite:100 #-}
{-# OPTIONS --with-K #-}
module Prelude.Tactics.Rewrite where

open import Prelude.Init
open Meta
open import Prelude.Generics
open Debug ("rewrite" , 100)

open import Prelude.DecEq
open import Prelude.General

open import Prelude.Functor
open import Prelude.Bifunctor
open import Prelude.Applicative
open import Prelude.Monad
open import Prelude.Semigroup
open import Prelude.Show
open import Prelude.Ord
open import Prelude.Membership
open import Prelude.Nary

private variable A : Set 

viewEq : Term  TC (Term × Term)
viewEq eq = do
  (def (quote _≡_) (_  _  vArg x  vArg y  []))  inferType eq
    where _  error "Can only write with equalities `x ≡ y`."
  return (x , y)

module _ (apply⁇ :   Bool) where

  getFocus : Term  Term  Term
  getFocus x =  "◆" ⇒_  proj₂  go 0 0
    where
      go :     Term  Bool × Term
      go k n t =
        if (x == t) then
          true , (if apply⁇ k then (var n []) else x)
        else case t of λ where
          (con c as)  map₂ (con c) (goArgs k as)
          (def s as)  let b , as′ = goArgs k as
                      in b , def s as′
          (lam v (abs s a)) 
            let b , a′ = go k (suc n) a
            in b , lam v (abs s a′)
          (pat-lam cs as) 
            let b , cs′  = goCs k cs
                k′       = if b then suc k else k
                b′ , as′ = goArgs k′ as
            in  b  b′ , pat-lam cs′ as′
          (pi (arg i a) (abs s P)) 
            let b , a′  = go k n a
                k′      = if b then suc k else k
                b′ , P′ = go k′ (suc n) P
            in (b  b′) , pi (arg i a′) (abs s P′)
          _  false , t
        where
          goArgs :   Args Term  Bool × Args Term
          goArgs _ []       = false , []
          goArgs k (arg i a  as) =
            let b , a′   = go k n a
                k′       = if b then suc k else k
                b′ , as′ = goArgs k′ as
            in b  b′ , arg i a′  as′

          goTel :   Telescope  Bool × Telescope
          goTel _ []       = false , []
          goTel k ((s , arg i t)  ts) =
            let b , t′   = go k n t
                k′       = if b then suc k else k
                b′ , ts′ = goTel k′ ts
            in b  b′ , (s , arg i t′)  ts′

          mutual
            goP :   Pattern  Bool × Pattern
            goP k = λ where
              (con c ps)  map₂ (con c) (goPs k ps)
              (dot t)  map₂ dot $ go k n t
              p  false , p

            goPs :   Args Pattern  Bool × Args Pattern
            goPs _ []       = false , []
            goPs k (arg i p  ps) =
              let b , p′   = goP k p
                  k′       = if b then suc k else k
                  b′ , ps′ = goPs k′ ps
              in b  b′ , arg i p′  ps′

          goC :   Clause  Bool × Clause
          goC k = λ where
            (clause tel ps t) 
              let b , tel′  = goTel k tel
                  k′        = if b then suc k else k
                  b′ , ps′  = goPs k′ ps
                  k″        = if b′ then suc k′ else k′
                  b″ , t′   = go k″ n t
              in b  b′  b″ , clause tel′ ps′ t′
            (absurd-clause tel ps) 
              let b , tel′  = goTel k tel
                  k′        = if b then suc k else k
                  b′ , ps′  = goPs k′ ps
              in b  b′ , absurd-clause tel′ ps′

          goCs :   List Clause  Bool × List Clause
          goCs _ []       = false , []
          goCs k (c  cs) =
            let b , c′   = goC k c
                k′       = if b then suc k else k
                b′ , cs′ = goCs k′ cs
            in b  b′ , c′  cs′

  `subst `subst˘ : Type  Term  Term  Term  Term
  `subst  ty x eq t = quote subst ∙⟦ getFocus x ty  eq  t 
  `subst˘ ty x eq t = `subst ty x (quote sym ∙⟦ eq ) t

  rw : (Term  Term  Term  Term)  Term  A  Tactic
  rw {A = A} sub eq `t hole = do
    t  quoteTC (A  `t)
    x , y  viewEq eq
    print $ "Rewriting: "  show x  " ≡ "  show y
           "\n\t in:"  show t
    let t′ = sub x eq t
    print $ " ⇒⇒⇒ "  show t′
    unify hole t′

  rwAt : A  Term  Tactic
  rwAt {A = A} `t eq hole = do
    ty  quoteTC A
    rw (`subst ty) eq `t hole

  rwBy : Term  A  Tactic
  rwBy eq `t hole = do
    ty  inferType hole
    rw (`subst˘ ty) eq `t hole

 :   Bool
 = const true

macro
  ⟪_⟫_≈:_ = rwBy
  ⟪_⟫_:≈_ = rwAt
  _≈:_    = rwBy 
  _:≈_    = rwAt 

  ⟪[_]⟫_≈:_ :  {n}   ^ n  Term  A  Tactic
  ⟪[ is ]⟫ eq ≈: t = rwBy (_∈ᵇ ⟦_⟧ {F = List} is) eq t

  ⟪[_]⟫_:≈_ :  {n}   ^ n  A  Term  Tactic
  ⟪[ is ]⟫ t :≈ eq = rwAt (_∈ᵇ ⟦_⟧ {F = List} is) t eq

private
  rw-just :  {m} {n : }  m  just n  Is-just m
  rw-just eq
    -- rewrite eq = M.Any.just tt
    -- = subst Is-just (sym eq) (M.Any.just tt)
    = eq ≈: M.Any.just tt
    -- = M.Any.just tt :≈ eq -- does not work

  postulate
    X : Set
    a b : X
    eq : a  b

    P : Pred₀ X
    Pa : P a

  open MultiTest

  _ = P b
   ∋⋮ subst  x  P x) eq Pa
     Pa :≈ eq
     sym eq ≈: Pa
    ⋮∅

  _ = P a  P b
   ∋⋮ subst  x  P a  P x) eq refl
     subst  x  P x  P b) (sym eq) refl
     eq ≈: refl
     sym eq ≈: refl
      _== 1  refl {x = P a} :≈ eq
     ⟪[ 1 , 2 , 3 ]⟫ refl {x = P a} :≈ eq
    ⋮∅

  postulate
     : Rel₀ X
    P²a :  a a

  _ =  b b
   ∋⋮ subst  x   x x) eq P²a
     P²a :≈ eq
     sym eq ≈: P²a
    ⋮∅

  postulate
     : 3Rel₀ X
    P³a :  a b a

  _ =  b a a
   ∋⋮ ⟪[ 1 ]⟫ (⟪[ 0 ]⟫ P³a :≈ eq) :≈ sym eq
     ⟪[ 0 ]⟫ eq ≈: ⟪[ 0 ]⟫ P³a :≈ eq
    ⋮∅

  postulate g : P b  X

  _ = ( λ (A : Set)  A)
   ∋⋮ (-, g (Pa :≈ eq))
     (-, g (sym eq ≈: Pa))
    ⋮∅

  postulate
    f : P a  P b  X
    f′ : (P a  P b) × (P b  P a)  X

  rw-in-argument : X
  rw-in-argument = f Pa≡Pb
    where Pa≡Pb : P a  P b
          Pa≡Pb rewrite eq = refl

  _ = X
   ∋⋮ f $ subst  x  P a  P x) eq refl
     f $ subst  x  P x  P b) (sym eq) refl
     (f $  _== 1  refl {x = P a} :≈ eq)
     f $ eq ≈: refl
    ⋮∅

  _ = X
   ∋⋮ f′ $ eq     ≈: (refl , refl)
     f′ $ sym eq ≈: (refl , refl)
    ⋮∅