{-# LANGUAGE TemplateHaskell, CPP #-}
module Data.Express.Name.Derive
( deriveName
, deriveNameCascading
, deriveNameIfNeeded
)
where
import qualified Data.Express.Name as N
import Control.Monad
import Data.Char
import Data.List
import Data.Express.Utils.TH
deriveName :: Name -> DecsQ
deriveName :: Name -> DecsQ
deriveName = Name -> (Name -> DecsQ) -> Name -> DecsQ
deriveWhenNeededOrWarn ''N.Name Name -> DecsQ
reallyDeriveName
deriveNameIfNeeded :: Name -> DecsQ
deriveNameIfNeeded :: Name -> DecsQ
deriveNameIfNeeded = Name -> (Name -> DecsQ) -> Name -> DecsQ
deriveWhenNeeded ''N.Name Name -> DecsQ
reallyDeriveName
deriveNameCascading :: Name -> DecsQ
deriveNameCascading :: Name -> DecsQ
deriveNameCascading = Name -> (Name -> DecsQ) -> Name -> DecsQ
deriveWhenNeeded ''N.Name Name -> DecsQ
reallyDeriveNameCascading
reallyDeriveName :: Name -> DecsQ
reallyDeriveName :: Name -> DecsQ
reallyDeriveName Name
t = do
(Type
nt,[Type]
vs) <- Name -> Q (Type, [Type])
normalizeType Name
t
Bool
isNum <- Name
t Name -> Name -> Q Bool
`isInstanceOf` ''Num
[d| instance N.Name $(Type -> Q Type
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return Type
nt) where
name _ = $(String -> Q Exp
forall (m :: * -> *). Quote m => String -> m Exp
stringE (String -> Q Exp) -> String -> Q Exp
forall a b. (a -> b) -> a -> b
$ Bool -> String
vname Bool
isNum) |]
where
showJustName :: Name -> String
showJustName = String -> String
forall a. [a] -> [a]
reverse (String -> String) -> (Name -> String) -> Name -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'.') (String -> String) -> (Name -> String) -> Name -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. [a] -> [a]
reverse (String -> String) -> (Name -> String) -> Name -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> String
forall a. Show a => a -> String
show
vname :: Bool -> String
vname Bool
True = String
"x"
vname Bool
False = (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
1 (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Name -> String
showJustName Name
t
reallyDeriveNameCascading :: Name -> DecsQ
reallyDeriveNameCascading :: Name -> DecsQ
reallyDeriveNameCascading = Name -> (Name -> DecsQ) -> Name -> DecsQ
reallyDeriveCascading ''N.Name Name -> DecsQ
reallyDeriveName