module Language.MSH.CodeGen.Object where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Language.MSH.StateDecl
import Language.MSH.CodeGen.Shared
import Language.MSH.CodeGen.Interop
supField :: String -> Type -> VarStrictType
supField c pt = (fname, NotStrict, ftype)
where
fname = mkName $ "_" ++ c ++ "_sup"
ftype = pt
dataField :: String -> [String] -> VarStrictType
dataField c vars = (fname, NotStrict, ftype)
where
fname = mkName $ "_" ++ c ++ "_data"
ftype = appN (ConT $ mkName $ c ++ "State") vars
subField :: String -> Name -> [String] -> VarStrictType
subField c s vars = (fname, NotStrict, ftype)
where
fname = mkName $ "_" ++ c ++ "_sub"
ftype = appN (VarT s) vars
objectCtrCxt :: String -> [String] -> Name -> Name -> Q Cxt
objectCtrCxt name vars s d = do
let
clname = mkName $ name ++ "Like"
tyname = mkName $ name ++ "M"
ty = appN (ConT tyname) vars
tyvars = map (VarT . mkName) vars
return [foldl AppT (ConT clname) ([VarT s, VarT d, ty] ++ tyvars)]
dataCtr :: String -> [String] -> Q Con
dataCtr name vars = do
let
cname = mkName $ name ++ "Data"
return $ RecC cname [dataField name vars]
startCtr :: String -> [String] -> Q Con
startCtr name vars = do
s <- newName "s"
d <- newName "d"
cxt <- objectCtrCxt name vars s d
let
cname = mkName $ name ++ "Start"
return $ ForallC [PlainTV s, PlainTV d] cxt $ RecC cname [
dataField name vars,
subField name s vars]
endCtr :: String -> [String] -> Type -> Q Con
endCtr name vars p = do
let
cname = mkName $ name ++ "End"
return $ RecC cname [
supField name p,
dataField name vars]
middleCtr :: String -> [String] -> Type -> Q Con
middleCtr name vars p = do
s <- newName "s"
d <- newName "d"
cxt <- objectCtrCxt name vars s d
let
cname = mkName $ name ++ "Middle"
return $ ForallC [PlainTV s, PlainTV d] cxt $ RecC cname [
supField name p,
dataField name vars,
subField name s vars]
genObjectCtrs :: StateDecl -> Q [Con]
genObjectCtrs (StateDecl {
stateMod = m,
stateName = name,
stateParams = vars,
stateParent = Nothing}) = do
dctr <- dataCtr name vars
case m of
Just Final -> return [dctr]
_ -> do
sctr <- startCtr name vars
return [dctr, sctr]
genObjectCtrs (StateDecl {
stateMod = m,
stateName = name,
stateParams = vars,
stateParentN = (Just p) } ) = do
sctr <- startCtr name vars
mctr <- middleCtr name vars (parseType p)
dctr <- dataCtr name vars
ectr <- endCtr name vars (parseType p)
case m of
Nothing -> return [dctr, sctr, ectr, mctr]
Just Abstract -> return [sctr, mctr]
Just Final -> return [dctr, ectr]
genStateObject :: [TyVarBndr] -> StateDecl -> Q Dec
genStateObject tyvars s@(StateDecl { stateName = name }) = do
let
oname = mkName $ name
cs <- genObjectCtrs s
return $ DataD [] oname tyvars cs []