module Types.Data.Num.Decimal.Literals.TH where

import Language.Haskell.TH

decLiteralT :: Integer -> Q Type
decLiteralT n = appT (conT (mkName "Dec")) (decLiteralT' n)
    where decLiteralT' n | n < 0     = appT (conT (mkName "Neg'")) (decLiteralT' (-n))
                         | n == 0    = conT (mkName "DecN")
                         | otherwise = appT (appT (conT (mkName ":.")) (decLiteralT' (n `div` 10))) (conT (mkName ("Dec" ++ show (n `mod` 10))))

decLiteralD :: String
            -> String
            -> Integer
            -> Q [Dec]
decLiteralD typePrefix valPrefix n =
    do let suffix = if n < 0 then "N" ++ show (-n) else show n
           typeName = mkName $ typePrefix ++ suffix
           valName = mkName $ valPrefix ++ suffix
       tySyn <- tySynD typeName [] (decLiteralT n)
       sig   <- sigD valName (conT typeName)
       val   <- valD (varP valName) (normalB [| undefined |]) []
       return [ tySyn, sig, val ]

decLiteralsD :: String
             -> String
             -> Integer
             -> Integer
             -> Q [Dec]
decLiteralsD typePrefix valPrefix from to =
    fmap concat $ sequence $ [ decLiteralD typePrefix valPrefix n | n <- [from..to] ]