[Template-haskell] Saving the AST generated by Template Haskell

Alfonso Acosta alfonso.acosta at gmail.com
Thu Jan 25 15:09:56 EST 2007


Hi all,

I'm using Template Haskell to design a small subset of a Hardware
Description DSEL (Domain Specific Embedded Language).

My language supports higher order as the user can supply small
functions as arguments. I chose to parse them with TH because it
allows me to use plain Haskell for the function syntax (instead of
reinventing the wheel) but mostly because gives parsing for free.

The AST of the functions must be kept by the embedded compiler so that
it can be later translated to a target language by one of the
potential backends of the embedded compiler.

The problem is ... how to store that AST?

Let me show an example

----
import Language.Haskell.TH.Syntax

-- sample function from the DSLE library
hdMapSY :: (HDPrimType a, HDPrimType b) =>  HDFun (a -> b) -> HDSignal
a ->  HDSignal b


-- We keep the function's AST (to make program transformations in the backends)
newtype HDPrimFun = HDPrimFun [Dec]
 deriving Show

-- Type safety layer,  we keep the function to make sure TH checks the
type (and possible further simulations)
data HDFun a = HDFun [Dec] a
 deriving Show

-- Helper constructor function, which suffers from the Saving-the-AST problem
-- mkMetaAST currently returns a phony value
mkHDFun :: Q [Dec] -> Q Exp
mkHDFun qd = do dx <- qd
                metaASTnm <- newName "metaAST"
                let funnm = getFunName dx
                    metaAST = mkMetaAST dx
                    metaASTdec = ValD (VarP metaASTnm) (NormalB metaAST) []
                return $ LetE (metaASTdec:dx) (AppE
                                                (AppE
                                                  (ConE $ mkName "HDFun")
                                                  (AppE
                                                    (ConE $ mkName "HDPrimFun")
                                                    (VarE metaASTnm)))
                                                (VarE funnm))

 where getFunName :: [Dec] -> Name
       getFunName [FunD nm _] = nm
       getFunName _ = error "mkHDFun: toy example, just and exactly one dec!"
       -- This function should create an AST expression from the AST
       -- but it would be a big pain to code
       mkMetaAST :: [Dec] -> Exp
       mkMetaAST _ = AppE (ConE (mkName "LitE"))
                                        (LitE (StringL "big pain to code!"))

---

An example program coded in the DSLE could could be something like ..

myCircuit :: HDSignal Int -> HDSignal Int
myCircuit = hdMapSY ($mkHDFun [d| f input = input+1 |])


So the question is ..

How can mkHDfun save the AST of "f input = input+1"  (for which it
needs to create and return  a metaAST) without the effort of having to
create boiler plate code for the whole TH library types?

Did anyone do something similar before?

I workaround would be saving the String of the AST with show, but Dec
nor Exp belong to the Read class, :S

Thanks in advance,

Alfonso Acosta


More information about the template-haskell mailing list