module Language.MSH.CodeGen.Decls (
genStateDecls
) where
import Control.Applicative ((<$>))
import Control.Monad (replicateM)
import Control.Monad.Except (runExcept)
import Data.Char (toLower)
import Data.Graph (stronglyConnComp)
import qualified Data.Map as M
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Control.Lens.TH
import Control.Lens.Internal.FieldTH
import qualified Language.Haskell.Exts.Syntax as Syntax
import qualified Language.Haskell.Exts.Parser as Exts
import Language.Haskell.Exts.Extension
import Language.Haskell.Meta.Syntax.Translate (toType, toDecs, toExp)
import Language.MSH.StateDecl
import Language.MSH.StateEnv
import Language.MSH.Constructor
import Language.MSH.Parsers
import Language.MSH.CodeGen.Shared
import Language.MSH.CodeGen.Interop
import Language.MSH.CodeGen.Data
import Language.MSH.CodeGen.Object
import Language.MSH.CodeGen.Monad
import Language.MSH.CodeGen.Class
import Language.MSH.CodeGen.Instances
import Language.MSH.CodeGen.Methods
import Language.MSH.CodeGen.Constructors
import Language.MSH.CodeGen.MiscInstances
import Language.MSH.CodeGen.Inheritance
genIdentityInstance :: Q Dec
genIdentityInstance = do
let
ty = tuple []
return $ InstanceD [] ty []
lensLookup :: Name -> [Name] -> Name -> [DefName]
lensLookup _ fs field = [TopName $ mkName $ nameBase field ++ "_lens"]
stateLensRules :: LensRules
stateLensRules = lensRules
genStateDecl :: StateEnv -> StateDecl -> Q [Dec]
genStateDecl env s@(StateDecl { stateParams = vars, stateBody = decls }) = do
let
tyvars = map (PlainTV . mkName) vars
d <- genStateData tyvars s
ls <- makeFieldOpticsForDec stateLensRules d
t <- genStateType tyvars s
o <- genStateObject tyvars s
c <- genStateClass env tyvars decls s
is <- genStateInstances env c decls s
cs <- genConstructors env s
misc <- genMiscInstances s o cs
ms <- genMethods env s (stateName s) vars decls
return $ [d,t,o,c] ++ is ++ ls ++ [sctrDec cs] ++ ms ++ misc
genStateDecls :: StateEnv -> Q [Dec]
genStateDecls env = case runExcept $ buildStateGraph env of
(Left err) -> fail $ show err
(Right env') -> do
dss <- mapM (genStateDecl env') (M.elems env')
return $ concat dss