TH - splicing with functions defined in the same source file

Simon Peyton-Jones simonpj at
Wed Nov 29 21:12:48 EST 2006

I think that in principle you can do this.  I see three issues

1.  You have to identify the CodeCutDecl points.
2.  You have to compile all the code before your cut-point to byte-code, just in case it's invoked by a splice afterwards.  This is in addition to compiling it to machine code (assuming that's what the main compilation does).
3.  I don't have a good handle on how complicated (or otherwise) it'd be to achieve all this.

Concerning (1), GHC already has something a bit like this.  The module is already renamed-and-typechecked in chunks, separated by top-level declaration splices.  This chunk at a time stuff (done by tcRnSrcDecls) could additionally compile the chunk to byte-code, just in case, without much difficulty. I think.

But you might want a finer granularity, so you can say
        f x = ...
        g = ...$(f 3)....
which would current be compiled as part of a single chunk.

Concerning (2), the thought of compiling all of every module to bytecode, on the off chance that a later splice might need it, seems unattractive to me (although it might work fine).  To predict, instead, which definitions will be needed means looking at the free variables of later splices, and taking a kind of transitive closure.  Possible but sounds like real work.  This is probably the main reason I've never attempted it.

But I don't think there's any reason in principle why it could not be done.


| -----Original Message-----
| From: glasgow-haskell-users-bounces at [mailto:glasgow-haskell-users-
| bounces at] On Behalf Of Clemens Fruhwirth
| Sent: 28 November 2006 15:55
| To: glasgow-haskell-users at
| Subject: TH - splicing with functions defined in the same source file
| Hi,
| Template Haskell has the restriction that I can not use a function in
| splices which is defined in the same source file the splice is in. I
| want to lift this restriction but at the moment I'm not sure which
| way to go.
| For simplicity, I'm not aiming at a dependency analysis approach
| because of things like f = $(..g..); g = $(..f..). Sure  can be
| caught, but I rather want to start slowly.
| The idea is to introduce a special marker in HsDecl, that allows all
| HsDecl after the marker to use functions defined before the
| marker. Let's call this marker CodeCutDecl. It partitions the list of
| decls right-associatively and is set explicitly by the programmer.
| My approach is as follows: Look at the
| TcRnDriver.lhs:tcRnSrcDecls. The tc_rn_src_decls cuts the code into
| groups of SpliceDecls. We do something similar, namely we insert an
| additional grouping step, partitioning groups of HsDecl
| right-associatively separated by CodeCutDecl. These are in turn are
| grouped by SpliceDecls as before. Let's call this new grouping
| function tc_rn_cut_decls.
| Let preceeeding_decls be the list of HsDecls before the CodeCutDecl
| marker. We assume preceeding_decls to be renamed and type checked, and
| initially empty. Whenever entering tc_rn_cut_decls, the
| preceeding_decls list is compiled and linked. Similar to
| tc_rn_src_decls, the remaining decls are partitioned into a
| first_code_cut and remaining_decls group, separated by CodeCutDecl (or
| exhausition of the list making the reamining_decls list
| empty). first_code_cut is renamed/type checked. It becomes the
| preceeding_decls list for the next invokation of tc_src_cut_decls.
| Compiling preceeding_decls to interactive code should enable the
| type-checker in the subsequent invocations to use this compiled code
| in expression/decl splicing.
| The compilation in detail should happen by a special variant of
| hscCompileInteractive that does not have a file frontend, but one
| that directly supplies the compiler with a renamed/type-check source
| being the preceeding_decls list. The result goes through byteCodeGen
| via the hscInteractive backend, ending up as an (InteractiveRecomp _
| comp_bc, _, _). The comp_bc is transformed into Linkables with [BCOs
| comp_bc] and linked with linkModules of ghci/Linker.lhs.
| My question: Is this a sensible approach? Is it sufficient to remove
| the stage checking in thLocalId to make the type checker use the
| preceeding BCO-compiled code in its invokations of
| HscMain.compileExpr? Do you think I have to unload the byte compiled
| code for some reason I can't think of?
| Thanks for any guidance,
| ---
| Fruhwirth Clemens -
| for robots: sp4mtrap at
| _______________________________________________
| Glasgow-haskell-users mailing list
| Glasgow-haskell-users at

More information about the Glasgow-haskell-users mailing list