module Language.MSH.CodeGen.ObjectInstance (
genObjectInstance
) where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Language.MSH.StateDecl
import Language.MSH.CodeGen.Shared
genObjectTypeInsts :: Type -> Type -> Q [Dec]
genObjectTypeInsts obj st = do
m <- VarT `fmap` newName "m"
s <- VarT `fmap` newName "st"
r <- VarT `fmap` newName "r"
t <- VarT `fmap` newName "ty"
return [ TySynInstD (mkName "QueryObject") $ TySynEqn [obj] obj
, TySynInstD (mkName "QueryMonad") $ TySynEqn [obj, m] m
, TySynInstD (mkName "QueryResult") $ TySynEqn [obj, t, s, m, r]
(foldl AppT (ConT $ mkName "RunnableQuery") [ ConT (mkName "ExtCall")
, obj, st, m, r ])]
genObjectInstance :: StateDecl -> Q [Dec]
genObjectInstance (StateDecl { stateName = name, stateParams = bars }) = do
let
obj = appN (ConT $ mkName name) bars
st = appN (ConT $ mkName $ name ++ "State") bars
m <- newName "m"
let
cxt = [AppT (ConT $ mkName "Monad") (VarT m)]
ty = AppT (AppT (AppT (ConT $ mkName "Object") obj) st) (VarT m)
ost = TySynInstD (mkName "ObjSt") $ TySynEqn [obj] st
cl1 = Clause [VarP $ mkName "obj", ConP (mkName "MkMethod") [WildP, VarP $ mkName "e"]] (NormalB $ AppE (ConE $ mkName "MkExtCall") (AppE (VarE $ mkName "e") (VarE $ mkName "obj"))) []
cl2 = Clause [VarP $ mkName "obj", ConP (mkName "MkField") [VarP $ mkName "eg", WildP, WildP, WildP]] (NormalB $ AppE (ConE $ mkName "MkExtCall") (AppE (VarE $ mkName "eg") (VarE $ mkName "obj"))) []
eqn = FunD (mkName ".!") [cl1, cl2]
ds = [ eqn]
fams <- genObjectTypeInsts obj st
return $ InstanceD cxt ty ds : fams
genObjectInstance _ = return []