module GLL.Combinators.Memoisation where

import              Data.IORef
import qualified    Data.IntMap     as IM

-- | use <::=> to enforce using parse context (to handle left-recursion)
type MemoTable a = IM.IntMap (IM.IntMap a)
type MemoRef a   = IORef (MemoTable a)

memLookup :: (Int, Int) -> MemoTable a -> Maybe a
memLookup (l,r) = maybe Nothing look' . IM.lookup l
 where  look' = maybe Nothing Just . IM.lookup r 

memInsert :: (Int, Int) -> a -> MemoTable a -> MemoTable a
memInsert (l,r) as = IM.alter add' l
 where  add' mm = case mm of
                    Nothing -> Just $ IM.singleton r as
                    Just m  -> Just $ IM.insert r as m

-- create a new memo-table to use with the memo function
newMemoTable :: IO (MemoRef a)
newMemoTable = newIORef IM.empty