packages feed

hoop-0.3.0.0: src/Language/MSH/CodeGen/Methods.hs

--------------------------------------------------------------------------------
-- Monadic State Hierarchies                                                  --
-- Copyright 2013-2019 Michael B. Gale (m.gale@warwick.ac.uk)                 --
--------------------------------------------------------------------------------

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.MethodTable
import Language.MSH.CodeGen.Shared 
import Language.MSH.CodeGen.Inheritance

--------------------------------------------------------------------------------

genMethodBody :: Name -> Dec -> Dec 
genMethodBody name (ValD (VarP _) body wh) =  ValD (VarP name) body wh
genMethodBody name (FunD _ cs) = FunD name cs

genMethod' :: String -> String -> [String] -> Type -> Dec -> Q [Dec]
genMethod' className name vars ty def = do 
    o <- newName "o"
    s <- newName "s"
    m <- newName "m"
    let
        n'  = mkName $ "_" ++ className ++ "_" ++ name
        svs = appN (VarT s) vars
        stt = AppT (AppT (ConT (mkName "StateT")) svs) (VarT m)
        tvs = [PlainTV o, PlainTV s, PlainTV m] ++ [PlainTV (mkName v) | v <- vars]
        cxt = [foldl AppT (ConT $ mkName $ className ++ "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
     ,  genMethodBody n' def
     ]

-- | Generates a method belonging to a state class.
genMethod :: StateDecl -> String -> [String] -> (String, MethodEntry) -> Q [Dec]
genMethod decl n vars (name, entry)
    | abstractEntry entry = trace (name ++ " is abstract in " ++ show decl) $ return []
    | otherwise = case entry of 
        GenesisMethod _ (Just (SigD _ ty)) (Just def) -> 
            genMethod' n name vars ty def
        OverridenMethod (SigD _ ty) def -> 
            genMethod' n name vars ty def
        InheritedMethod _ (SigD _ ty) (Just def) ->
            genMethod' n name vars ty def
        _ -> error $ "[genMethod] Unexpected method table entry:\n " ++ show entry

-- 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

-- | Generates methods for a state class.
-- genMethods :: StateEnv -> StateDecl -> String -> [String] -> [Dec] -> Q [Dec]
-- genMethods env decl n vars ds = do
--     concat `fmap` mapM (genMethod env decl n vars) ds

-- | `genMethods` Generates methods for a state class.
genMethods :: StateDecl -> String -> [String] -> Q [Dec]
genMethods decl n vars =
    concat <$> mapM (genMethod decl n vars) ms
    where ms = M.toList $ methods $ stateMethods decl

--------------------------------------------------------------------------------