module U.Codebase.Sqlite.Symbol where

import Data.Set qualified as Set
import Data.Text (Text)
import Data.Word (Word64)
import U.Core.ABT.Var qualified as ABT

data Symbol = Symbol !Word64 !Text deriving (Symbol -> Symbol -> Bool
(Symbol -> Symbol -> Bool)
-> (Symbol -> Symbol -> Bool) -> Eq Symbol
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Symbol -> Symbol -> Bool
== :: Symbol -> Symbol -> Bool
$c/= :: Symbol -> Symbol -> Bool
/= :: Symbol -> Symbol -> Bool
Eq, Eq Symbol
Eq Symbol =>
(Symbol -> Symbol -> Ordering)
-> (Symbol -> Symbol -> Bool)
-> (Symbol -> Symbol -> Bool)
-> (Symbol -> Symbol -> Bool)
-> (Symbol -> Symbol -> Bool)
-> (Symbol -> Symbol -> Symbol)
-> (Symbol -> Symbol -> Symbol)
-> Ord Symbol
Symbol -> Symbol -> Bool
Symbol -> Symbol -> Ordering
Symbol -> Symbol -> Symbol
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Symbol -> Symbol -> Ordering
compare :: Symbol -> Symbol -> Ordering
$c< :: Symbol -> Symbol -> Bool
< :: Symbol -> Symbol -> Bool
$c<= :: Symbol -> Symbol -> Bool
<= :: Symbol -> Symbol -> Bool
$c> :: Symbol -> Symbol -> Bool
> :: Symbol -> Symbol -> Bool
$c>= :: Symbol -> Symbol -> Bool
>= :: Symbol -> Symbol -> Bool
$cmax :: Symbol -> Symbol -> Symbol
max :: Symbol -> Symbol -> Symbol
$cmin :: Symbol -> Symbol -> Symbol
min :: Symbol -> Symbol -> Symbol
Ord, Int -> Symbol -> ShowS
[Symbol] -> ShowS
Symbol -> String
(Int -> Symbol -> ShowS)
-> (Symbol -> String) -> ([Symbol] -> ShowS) -> Show Symbol
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Symbol -> ShowS
showsPrec :: Int -> Symbol -> ShowS
$cshow :: Symbol -> String
show :: Symbol -> String
$cshowList :: [Symbol] -> ShowS
showList :: [Symbol] -> ShowS
Show)

-- | This clever instance relies on Ord to synthesize a new id.
--  If i > i2, then s > vs; otherwise increment the max i2:
--     freshIn [(0,"foo"), (1,"bar")] (0,"cat") = (3, "cat")
instance ABT.Var Symbol where
  freshIn :: Set Symbol -> Symbol -> Symbol
freshIn Set Symbol
vs Symbol
s | Set Symbol -> Bool
forall a. Set a -> Bool
Set.null Set Symbol
vs Bool -> Bool -> Bool
|| Symbol -> Set Symbol -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.notMember Symbol
s Set Symbol
vs = Symbol
s -- already fresh!
  freshIn Set Symbol
vs s :: Symbol
s@(Symbol Word64
i Text
n) = case Int -> Set Symbol -> Symbol
forall a. Int -> Set a -> a
Set.elemAt (Set Symbol -> Int
forall a. Set a -> Int
Set.size Set Symbol
vs Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Set Symbol
vs of
    Symbol Word64
i2 Text
_ -> if Word64
i Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
i2 then Symbol
s else Word64 -> Text -> Symbol
Symbol (Word64
i2 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
1) Text
n