{-# OPTIONS --safe #-}
{-
  This code contains some helper functions for solvers.
  Variables in the sense of this files are things that are treated like variables by a solver.
  A ring solver might want to treat "f x" in an equation "f x + 0 ≡ f x" like a variable "y".
  During the inspection of the lhs and rhs of an equation, terms like "f x" are found and saved
  and later, indices are assigned to them. These indices will be the indices of the variables
  in the normal forms the solver uses.
-}
module Cubical.Tactics.Reflection.Variables where

open import Cubical.Foundations.Prelude hiding (Type)

open import Agda.Builtin.Reflection hiding (Type)
open import Agda.Builtin.String
open import Agda.Builtin.Float
open import Agda.Builtin.Word
open import Agda.Builtin.Char
open import Agda.Builtin.Nat using () renaming (_==_ to _=ℕ_)

open import Cubical.Reflection.Base
open import Cubical.Data.Bool
open import Cubical.Data.List
open import Cubical.Data.Maybe
open import Cubical.Data.Nat using ()

open import Cubical.Tactics.Reflection

private
  variable
     : Level


Vars = List Term
VarAss = Term  Maybe 
Template = VarAss  Term

private
  _=N_ = primQNameEquality
  _=M_ = primMetaEquality

  _=L_ : Literal  Literal  Bool
  nat n =L nat m = n =ℕ m
  word64 n =L word64 m = primWord64ToNat n =ℕ primWord64ToNat m
  float x =L float y = primFloatEquality x y
  char c =L char c' = primCharEquality c c'
  string s =L string s' = primStringEquality s s'
  name x =L name y = x =N y
  meta x =L meta y = x =M y
  _ =L _ = false

  compareVargs : List (Arg Term)  List (Arg Term)  Bool

  _=T_ : Term  Term  Bool  -- this should be a TC, since it should error out sometimes
  var index args =T var index' args' = (index =ℕ index') and compareVargs args args'
  con c args =T con c' args'   = (c =N c') and compareVargs args args'
  def f args =T def f' args'   = (f =N f') and compareVargs args args'
  lit l =T lit l'              = l =L l'
  meta x args =T meta x' args' = (x =M x') and compareVargs args args'
  _ =T _                       = false  -- this should be fixed

compareVargs [] [] = true
compareVargs (x v∷ l) (x' v∷ l') = (x =T x') and compareVargs l l'
compareVargs (_ h∷ l) (_ h∷ l') = compareVargs l l' -- ignore hargs, not sure this is good
compareVargs _ _ = false

addWithoutRepetition : Term  Vars  Vars
addWithoutRepetition t l@(t'  l') = if (t =T t') then l else t'  addWithoutRepetition t l'
addWithoutRepetition t []      = t  []

appendWithoutRepetition : Vars  Vars  Vars
appendWithoutRepetition (x  l) l' = appendWithoutRepetition l (addWithoutRepetition x l')
appendWithoutRepetition [] l' = l'

-- this can be used to get a map from variables to numbers 0,...,n
indexOf : Term  Vars  Maybe 
indexOf t (t'  l) =
  if (t =T t')
  then just 0
  else map-Maybe  k  ℕ.suc k) (indexOf t l)
indexOf t [] = nothing