{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

-- |
-- Module      :   Grisette.IR.SymPrim.Data.Prim.InternedTerm.SomeTerm
-- Copyright   :   (c) Sirui Lu 2021-2023
-- License     :   BSD-3-Clause (see the LICENSE file)
--
-- Maintainer  :   siruilu@cs.washington.edu
-- Stability   :   Experimental
-- Portability :   GHC only
module Grisette.IR.SymPrim.Data.Prim.InternedTerm.SomeTerm (SomeTerm (..)) where

import Data.Hashable (Hashable (hashWithSalt))
import Data.Typeable (Proxy (Proxy), typeRep)
import Grisette.IR.SymPrim.Data.Prim.InternedTerm.Term
  ( SupportedPrim,
    Term,
  )
import {-# SOURCE #-} Grisette.IR.SymPrim.Data.Prim.InternedTerm.TermUtils
  ( identityWithTypeRep,
  )

data SomeTerm where
  SomeTerm :: forall a. (SupportedPrim a) => Term a -> SomeTerm

instance Eq SomeTerm where
  (SomeTerm Term a
t1) == :: SomeTerm -> SomeTerm -> Bool
== (SomeTerm Term a
t2) = Term a -> (TypeRep, Id)
forall t. Term t -> (TypeRep, Id)
identityWithTypeRep Term a
t1 (TypeRep, Id) -> (TypeRep, Id) -> Bool
forall a. Eq a => a -> a -> Bool
== Term a -> (TypeRep, Id)
forall t. Term t -> (TypeRep, Id)
identityWithTypeRep Term a
t2

instance Hashable SomeTerm where
  hashWithSalt :: Id -> SomeTerm -> Id
hashWithSalt Id
s (SomeTerm Term a
t) = Id -> (TypeRep, Id) -> Id
forall a. Hashable a => Id -> a -> Id
hashWithSalt Id
s ((TypeRep, Id) -> Id) -> (TypeRep, Id) -> Id
forall a b. (a -> b) -> a -> b
$ Term a -> (TypeRep, Id)
forall t. Term t -> (TypeRep, Id)
identityWithTypeRep Term a
t

instance Show SomeTerm where
  show :: SomeTerm -> String
show (SomeTerm (Term a
t :: Term a)) = String
"<<" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Term a -> String
forall a. Show a => a -> String
show Term a
t String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" :: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ TypeRep -> String
forall a. Show a => a -> String
show (Proxy a -> TypeRep
forall {k} (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @a)) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
">>"