module Language.MSH.CodeGen.Methods (
genMethods
) where
import qualified Data.Map as M
import Debug.Trace
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Language.MSH.StateDecl
import Language.MSH.StateEnv
import Language.MSH.CodeGen.Shared
import Language.MSH.CodeGen.Inheritance
genMethod :: StateEnv -> StateDecl -> String -> [String] -> Dec -> Q [Dec]
genMethod env decl n vars (SigD name ty)
| isAbstract name decl = trace (nameBase name ++ " is abstract in " ++ show decl) $ return []
| otherwise = do
o <- newName "o"
s <- newName "s"
m <- newName "m"
let
n' = mkName $ "_" ++ n ++ "_" ++ nameBase name
svs = appN (VarT s) vars
stt = AppT (AppT (ConT (mkName "StateT")) svs) (VarT m)
tvs = [PlainTV o, PlainTV s, PlainTV m]
cxt = [foldl AppT (ConT $ mkName $ n ++ "Like") ([VarT o, VarT s, VarT m] ++ map (VarT . mkName) vars)]
return [
SigD n' $ unwrapForalls ty $ ForallT tvs cxt $ wrapMethodType False (\rt -> AppT stt rt) ty]
genMethod env decl n vars (ValD (VarP name) body wh) = do
let
n' = mkName $ "_" ++ n ++ "_" ++ nameBase name
return [ValD (VarP n') body wh]
genMethod env decl n vars (FunD name cs) = do
let
n' = mkName $ "_" ++ n ++ "_" ++ nameBase name
return [FunD n' cs]
genMethod env decl n vars dec = fail $
"Unsupported type of definition within a state class:\n" ++ show dec
genMethods :: StateEnv -> StateDecl -> String -> [String] -> [Dec] -> Q [Dec]
genMethods env decl n vars ds = do
concat `fmap` mapM (genMethod env decl n vars) ds