Jeffrey Straszhiem <[EMAIL PROTECTED]> wrote,
> On Wed, Aug 23, 2000 at 12:26:38PM +1000, Timothy Docker wrote:
> >
> > I'm writing a haskell program that generates C++ code based upon
> > some haskell data structures. At the moment, the code is somewhat
> > ugly with lots of stuff like
> >
> > mutatorDef structName (name,vtype) =
> > "inline void\n" ++
> > structName ++ "::" ++ (mutatorName name) ++
> > "( " ++ (cppParamType vtype) ++ " v ) {\n" ++
> > " " ++ (storageName name) ++ " = v;\n" ++
> > "}\n\n"
> >
> > All those ++ operators working on raw strings bug me, and manually
> > getting the indentation correct is a pain. Is there a more
> > functional approach to generating source code? I thought this could
> > be a common enough task that there could be a library, but a perusal
> > of haskell.org didn't seem to show anything relevant.
>
> To make matters worse, you're likely getting lousy efficiency with all
> of the ++ operators. Look through the code for showS in the Prelude
> for better ways to hook strings together. Paul Hudak talks about the
> efficient use of the show functions at:
>
> http://www.haskell.org/tutorial/stdclasses.html
>
> Now, with regard to the code being ugly, my suggestion would be to
> check out some of the pretty printer libraries out there, and to look
> through them. They basically solve a similar problem, except they
> first parse a normal program into a tree, then flatten the tree in a
> standard way. In your case you'll likely build the tree directly,
> then call the final stages of the pretty printer. There is no
> shortage of pretty printer libraries for Haskell, or for FP in
> general.
The canonical approach is to define an internal data
structure that represents C++ code, then let your mutator
functions generate values of that data type (instead of
strings), and finally pretty print values of this C++ data
structure. That's cleaner and more flexible than the ++
cascades (or the show equivalent).
Depending on how restricted and/or idiomatic the generate
C++ code is, it makes sense to not have a data structure
that can represent arbitrary C++ programs, but only a subset
that is relevant for the code generation task at hand. So,
you might want functions like
mutatorDef :: ... -> AbstractCPlusPlus
prettyPrintACPP :: AbstractCPlusPlus -> String
Cheers,
Manuel