{- |
Module      : Text.LLVM.Triple.Parse.LookupTable
Description : Helpers for parsing a finite set of strings.
License     : BSD3
Maintainer  : Langston Barrett
Stability   : experimental

This module is not exposed as part of the library API.
-}

{-# LANGUAGE TupleSections #-}

module Text.LLVM.Triple.Parse.LookupTable
  ( -- * Construction
    LookupTable
  , makeTable
  , enumTable
  , enumTableVariants
    -- * Queries
  , lookupBy
  , lookup
  , lookupByPrefix
  , lookupByWithDefault
  , lookupWithDefault
  , lookupByPrefixWithDefault
  , lookupBySuffixWithDefault
  ) where

import           Prelude hiding (lookup)
import qualified Data.Maybe as Maybe
import qualified Data.List as List

--------------------------------------------------------------------------------
-- Construction

-- | A table from constrant strings to values, to be used in parsing a finite
-- set of possibilities. Could be replaced by a fancier data structure, but
-- there's only one target triple per module, after all.
--
-- Hopefully, GHC is smart enough to construct these at compile-time.
newtype LookupTable a = LookupTable { forall a. LookupTable a -> [(String, a)]
getLookupTable :: [(String, a)] }

makeTable :: [(String, a)] -> LookupTable a
makeTable :: forall a. [(String, a)] -> LookupTable a
makeTable = [(String, a)] -> LookupTable a
forall a. [(String, a)] -> LookupTable a
LookupTable

enumTable :: Bounded a => Enum a => (a -> String) -> LookupTable a
enumTable :: forall a. (Bounded a, Enum a) => (a -> String) -> LookupTable a
enumTable a -> String
prnt = [(String, a)] -> LookupTable a
forall a. [(String, a)] -> LookupTable a
makeTable [(a -> String
prnt a
a, a
a) | a
a <- a -> [a]
forall a. Enum a => a -> [a]
enumFrom a
forall a. Bounded a => a
minBound]

enumTableVariants :: Bounded a => Enum a => (a -> [String]) -> LookupTable a
enumTableVariants :: forall a. (Bounded a, Enum a) => (a -> [String]) -> LookupTable a
enumTableVariants a -> [String]
prnt =
  [(String, a)] -> LookupTable a
forall a. [(String, a)] -> LookupTable a
makeTable ((a -> [(String, a)]) -> [a] -> [(String, a)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\a
a -> (String -> (String, a)) -> [String] -> [(String, a)]
forall a b. (a -> b) -> [a] -> [b]
map (,a
a) (a -> [String]
prnt a
a)) (a -> [a]
forall a. Enum a => a -> [a]
enumFrom a
forall a. Bounded a => a
minBound))

--------------------------------------------------------------------------------
-- Queries

lookupBy :: (String -> Bool) -> LookupTable a -> Maybe a
lookupBy :: forall a. (String -> Bool) -> LookupTable a -> Maybe a
lookupBy String -> Bool
p = [a] -> Maybe a
forall a. [a] -> Maybe a
Maybe.listToMaybe ([a] -> Maybe a)
-> (LookupTable a -> [a]) -> LookupTable a -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((String, a) -> a) -> [(String, a)] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (String, a) -> a
forall a b. (a, b) -> b
snd ([(String, a)] -> [a])
-> (LookupTable a -> [(String, a)]) -> LookupTable a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((String, a) -> Bool) -> [(String, a)] -> [(String, a)]
forall a. (a -> Bool) -> [a] -> [a]
filter (String -> Bool
p (String -> Bool) -> ((String, a) -> String) -> (String, a) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String, a) -> String
forall a b. (a, b) -> a
fst) ([(String, a)] -> [(String, a)])
-> (LookupTable a -> [(String, a)])
-> LookupTable a
-> [(String, a)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LookupTable a -> [(String, a)]
forall a. LookupTable a -> [(String, a)]
getLookupTable

lookup :: String -> LookupTable a -> Maybe a
lookup :: forall a. String -> LookupTable a -> Maybe a
lookup String
s = (String -> Bool) -> LookupTable a -> Maybe a
forall a. (String -> Bool) -> LookupTable a -> Maybe a
lookupBy (String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
s)

lookupByPrefix :: String -> LookupTable a -> Maybe a
lookupByPrefix :: forall a. String -> LookupTable a -> Maybe a
lookupByPrefix String
pfx = (String -> Bool) -> LookupTable a -> Maybe a
forall a. (String -> Bool) -> LookupTable a -> Maybe a
lookupBy (String
pfx String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`List.isPrefixOf`)

lookupByWithDefault :: a -> (String -> Bool) -> LookupTable a -> a
lookupByWithDefault :: forall a. a -> (String -> Bool) -> LookupTable a -> a
lookupByWithDefault a
def String -> Bool
p = a -> Maybe a -> a
forall a. a -> Maybe a -> a
Maybe.fromMaybe a
def (Maybe a -> a) -> (LookupTable a -> Maybe a) -> LookupTable a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Bool) -> LookupTable a -> Maybe a
forall a. (String -> Bool) -> LookupTable a -> Maybe a
lookupBy String -> Bool
p

lookupWithDefault :: LookupTable a -> a -> String -> a
lookupWithDefault :: forall a. LookupTable a -> a -> String -> a
lookupWithDefault LookupTable a
table a
def String
val = a -> (String -> Bool) -> LookupTable a -> a
forall a. a -> (String -> Bool) -> LookupTable a -> a
lookupByWithDefault a
def (String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
val) LookupTable a
table

lookupByPrefixWithDefault :: LookupTable a -> a -> String -> a
lookupByPrefixWithDefault :: forall a. LookupTable a -> a -> String -> a
lookupByPrefixWithDefault LookupTable a
table a
def String
pfx =
  a -> (String -> Bool) -> LookupTable a -> a
forall a. a -> (String -> Bool) -> LookupTable a -> a
lookupByWithDefault a
def (String
pfx String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`List.isPrefixOf`) LookupTable a
table

lookupBySuffixWithDefault :: LookupTable a -> a -> String -> a
lookupBySuffixWithDefault :: forall a. LookupTable a -> a -> String -> a
lookupBySuffixWithDefault LookupTable a
table a
def String
sfx =
  a -> (String -> Bool) -> LookupTable a -> a
forall a. a -> (String -> Bool) -> LookupTable a -> a
lookupByWithDefault a
def (String
sfx String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`List.isSuffixOf`) LookupTable a
table