Vladimir Prus


Wednesday, March 16, 2005

Generalizing from examples

Over time I wrote quite a lot of C++ code that generates other C++ code. At work I generate C++ from assembler, and I also worked on a parser generator called Whale. Code generation is a powerful approach, as shown by some other examples. And unlike template metaprogramming it does not stress today's compilers too much (for example, compilation speed is a recurring topic on Boost.Spirit mailing list.

But it's damn hard to write the code generator. When writing C++ code as a C++ literal, the look of the code is so strange that typos can hide anywhere. Then you build the code generator, use it to produce test code, and it fails to compile. And you're back to the beginning, hunting for missing semicolons.

The simple solution I've recently found is that new functionality should never be directly implemented in a code generator. First, you need to take the generated code and modify it, despite comments warning you that all changes will be lost. Once you've modified the generated code and it works, it's very easy to bring modifications back to code generator -- it can be even done by regex in emacs. And the generated code will work.

This brings us to the topic of the article. It's hardly a good idea to use very generic solution without trying specific examples. And an example is better that a generic advice, so here's another example: don't write a C++ template function from scratch. First write non-template function and debug it, and only then add template declaration and try with different template parameters.

No comments: