module Tactic.Nat.Subtract.Reflect where open import Prelude open import Builtin.Reflection open import Control.Monad.State open import Tactic.Reflection.Quote open import Tactic.Reflection.DeBruijn open import Tactic.Nat.Reflect open import Tactic.Nat.Subtract.Exp ⟨suc⟩s : SubExp → SubExp ⟨suc⟩s (lit n) = lit (suc n) ⟨suc⟩s (lit n ⟨+⟩ e) = lit (suc n) ⟨+⟩ e ⟨suc⟩s e = lit 1 ⟨+⟩ e freshS : Term → R SubExp freshS t = get >>= uncurry′ λ i Γ → var i <$ put (suc i , (t , i) ∷ Γ) pattern _`-_ x y = def (quote _-N_) (vArg x ∷ vArg y ∷ []) termToSubExpR : Term → R SubExp termToSubExpR (a `+ b) = _⟨+⟩_ <$> termToSubExpR a <*> termToSubExpR b termToSubExpR (a `* b) = _⟨*⟩_ <$> termToSubExpR a <*> termToSubExpR b termToSubExpR (a `- b) = _⟨-⟩_ <$> termToSubExpR a <*> termToSubExpR b termToSubExpR `0 = pure (lit 0) termToSubExpR (`suc a) = ⟨suc⟩s <$> termToSubExpR a termToSubExpR (lit (nat n)) = pure (lit n) termToSubExpR unknown = fail termToSubExpR t = gets (flip lookup t ∘ snd) >>= λ { nothing → freshS t ; (just i) → pure (var i) } termToSubEqR : Term → R (SubExp × SubExp) termToSubEqR (lhs `≡ rhs) = _,_ <$> termToSubExpR lhs <*> termToSubExpR rhs termToSubEqR _ = fail termToSubEq : Term → Maybe ((SubExp × SubExp) × List Term) termToSubEq t = runR (termToSubEqR t) pattern _`<_ a b = def (quote LessNat) (vArg a ∷ vArg b ∷ []) termToSubEqnR : Term → R Eqn termToSubEqnR (lhs `< rhs) = _:<_ <$> termToSubExpR lhs <*> termToSubExpR rhs termToSubEqnR (lhs `≡ rhs) = _:≡_ <$> termToSubExpR lhs <*> termToSubExpR rhs termToSubEqnR _ = fail termToSubEqn : Term → Maybe (Eqn × List Term) termToSubEqn t = runR (termToSubEqnR t) private lower : Nat → Term → R Term lower 0 = pure lower i = lift ∘ strengthen i termToSubHypsR′ : Nat → Term → R (List Eqn) termToSubHypsR′ i (hyp `-> a) = _∷_ <$> (termToSubEqnR =<< lower i hyp) <*> termToSubHypsR′ (suc i) a termToSubHypsR′ i a = [_] <$> (termToSubEqnR =<< lower i a) termToSubHypsR : Term → R (List Eqn) termToSubHypsR = termToSubHypsR′ 0 termToSubHyps : Term → Maybe (List Eqn × List Term) termToSubHyps t = runR (termToSubHypsR t) instance QuotableSubExp : Quotable SubExp QuotableSubExp = record { ` = quoteSubExp } where quoteSubExp : SubExp → Term quoteSubExp (var x) = con (quote SubExp.var) (vArg (` x) ∷ []) quoteSubExp (lit n) = con (quote SubExp.lit) (vArg (` n) ∷ []) quoteSubExp (e ⟨+⟩ e₁) = con (quote SubExp._⟨+⟩_) (map defaultArg $ quoteSubExp e ∷ quoteSubExp e₁ ∷ []) quoteSubExp (e ⟨-⟩ e₁) = con (quote SubExp._⟨-⟩_) (map defaultArg $ quoteSubExp e ∷ quoteSubExp e₁ ∷ []) quoteSubExp (e ⟨*⟩ e₁) = con (quote SubExp._⟨*⟩_) (map defaultArg $ quoteSubExp e ∷ quoteSubExp e₁ ∷ []) QuotableEqn : Quotable Eqn QuotableEqn = record { ` = quoteEqn } where quoteEqn : Eqn → Term quoteEqn (a :≡ b) = con (quote _:≡_) (vArg (` a) ∷ vArg (` b) ∷ []) quoteEqn (a :< b) = con (quote _:<_) (vArg (` a) ∷ vArg (` b) ∷ [])