{-# LANGUAGE ScopedTypeVariables #-}

-- |
-- Module      :   Grisette.Internal.Backend.SymBiMap
-- 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.Internal.Backend.SymBiMap
  ( SymBiMap (..),
    emptySymBiMap,
    sizeBiMap,
    addBiMap,
    addBiMapIntermediate,
    findStringToSymbol,
    lookupTerm,
  )
where

import Data.Dynamic (Dynamic)
import qualified Data.HashMap.Strict as M
import GHC.Stack (HasCallStack)
import Grisette.Internal.SymPrim.Prim.SomeTerm
  ( SomeTerm,
  )
import Grisette.Internal.SymPrim.Prim.Term
  ( SomeTypedSymbol,
  )

data SymBiMap = SymBiMap
  { SymBiMap -> HashMap SomeTerm Dynamic
biMapToSBV :: M.HashMap SomeTerm Dynamic,
    SymBiMap -> HashMap String SomeTypedSymbol
biMapFromSBV :: M.HashMap String SomeTypedSymbol
  }
  deriving (Int -> SymBiMap -> ShowS
[SymBiMap] -> ShowS
SymBiMap -> String
(Int -> SymBiMap -> ShowS)
-> (SymBiMap -> String) -> ([SymBiMap] -> ShowS) -> Show SymBiMap
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SymBiMap -> ShowS
showsPrec :: Int -> SymBiMap -> ShowS
$cshow :: SymBiMap -> String
show :: SymBiMap -> String
$cshowList :: [SymBiMap] -> ShowS
showList :: [SymBiMap] -> ShowS
Show)

emptySymBiMap :: SymBiMap
emptySymBiMap :: SymBiMap
emptySymBiMap = HashMap SomeTerm Dynamic
-> HashMap String SomeTypedSymbol -> SymBiMap
SymBiMap HashMap SomeTerm Dynamic
forall k v. HashMap k v
M.empty HashMap String SomeTypedSymbol
forall k v. HashMap k v
M.empty

sizeBiMap :: SymBiMap -> Int
sizeBiMap :: SymBiMap -> Int
sizeBiMap = HashMap SomeTerm Dynamic -> Int
forall k v. HashMap k v -> Int
M.size (HashMap SomeTerm Dynamic -> Int)
-> (SymBiMap -> HashMap SomeTerm Dynamic) -> SymBiMap -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SymBiMap -> HashMap SomeTerm Dynamic
biMapToSBV

addBiMap :: (HasCallStack) => SomeTerm -> Dynamic -> String -> SomeTypedSymbol -> SymBiMap -> SymBiMap
addBiMap :: HasCallStack =>
SomeTerm
-> Dynamic -> String -> SomeTypedSymbol -> SymBiMap -> SymBiMap
addBiMap SomeTerm
s Dynamic
d String
n SomeTypedSymbol
sb (SymBiMap HashMap SomeTerm Dynamic
t HashMap String SomeTypedSymbol
f) = HashMap SomeTerm Dynamic
-> HashMap String SomeTypedSymbol -> SymBiMap
SymBiMap (SomeTerm
-> Dynamic -> HashMap SomeTerm Dynamic -> HashMap SomeTerm Dynamic
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
M.insert SomeTerm
s Dynamic
d HashMap SomeTerm Dynamic
t) (String
-> SomeTypedSymbol
-> HashMap String SomeTypedSymbol
-> HashMap String SomeTypedSymbol
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
M.insert String
n SomeTypedSymbol
sb HashMap String SomeTypedSymbol
f)

addBiMapIntermediate :: (HasCallStack) => SomeTerm -> Dynamic -> SymBiMap -> SymBiMap
addBiMapIntermediate :: HasCallStack => SomeTerm -> Dynamic -> SymBiMap -> SymBiMap
addBiMapIntermediate SomeTerm
s Dynamic
d (SymBiMap HashMap SomeTerm Dynamic
t HashMap String SomeTypedSymbol
f) = HashMap SomeTerm Dynamic
-> HashMap String SomeTypedSymbol -> SymBiMap
SymBiMap (SomeTerm
-> Dynamic -> HashMap SomeTerm Dynamic -> HashMap SomeTerm Dynamic
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
M.insert SomeTerm
s Dynamic
d HashMap SomeTerm Dynamic
t) HashMap String SomeTypedSymbol
f

findStringToSymbol :: String -> SymBiMap -> Maybe SomeTypedSymbol
findStringToSymbol :: String -> SymBiMap -> Maybe SomeTypedSymbol
findStringToSymbol String
s (SymBiMap HashMap SomeTerm Dynamic
_ HashMap String SomeTypedSymbol
f) = String -> HashMap String SomeTypedSymbol -> Maybe SomeTypedSymbol
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
M.lookup String
s HashMap String SomeTypedSymbol
f

lookupTerm :: (HasCallStack) => SomeTerm -> SymBiMap -> Maybe Dynamic
lookupTerm :: HasCallStack => SomeTerm -> SymBiMap -> Maybe Dynamic
lookupTerm SomeTerm
t SymBiMap
m = SomeTerm -> HashMap SomeTerm Dynamic -> Maybe Dynamic
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
M.lookup SomeTerm
t (SymBiMap -> HashMap SomeTerm Dynamic
biMapToSBV SymBiMap
m)