views:

185

answers:

5

In his FAQ @ http://www2.research.att.com/~bs/bs_faq.html#bootstrapping, Bjarne Stroustrup says:

To build [Cfront, the first C++ compiler], I first used C to write a "C with Classes"-to-C preprocessor. "C with Classes" was a C dialect that became the immediate ancestor to C++... I then wrote the first version of Cfront in "C with Classes".

When I read this, it piqued my interest in the C preprocessor. I'd seen its macro capabilities as suitable for simplifying common expressions but hadn't thought about its ability to significantly add to syntax and semantics on the level that I imagine bringing classes to C took.

So now I have a couple of questions on my mind:

1) Are there other examples of this approach to bootstrapping a language off of C?

2) Is the source to Stroustrup's original work available anywhere?

3) Where could I learn more about the specifics of utilizing this technique?

4) What are the lengths/limits of that approach? Could one, say, create a set of preprocessor macros that let someone write in something significantly Lisp/Scheme like?

+11  A: 

Note that Stroustrup is not saying that he used the C preprocessor (cpp) to create C With Classes -he didn't. He wrote his own preprocessor using C. And Cfront was a true compiler not a preprocessor at all. The C preprocessor is in fact deeply unsuitable for language development, as it has no parsing abilities whatsoever.

anon
Few parsing abilities. Macro parameter lists require a little bit of processing that raises to the level of parsing. To handle `FOO( (x, y, z), a, b, "me, myself, and I")` it has to do parenthesis depth.
nategoose
@nategoose Of course it can parse C preprocessor macros - that is what it was designed to do! But to write things like C With Classes, it has to be able to parse the C With Classes code, and it cannot do that.
anon
+4  A: 

The C preprocessor isn't what you're looking for. It can't add syntax and semantics like Cfront did.

Cfront was an actual compiler that translated C with Classes, later C++, to C. It was a preprocessor only in that it ran before the C compiler. I used a program called f2c once to translate FORTRAN 77 code to C code. It worked on the same principle.

There are languages like Common Lisp with enough macro power to add new syntax and semantics, and languages like Forth where the system is flexible enough to accomodate changes, but that won't work for most languages.

David Thornley
+1  A: 

It sounds like his "C with Classes"-to-C preprocessor was not the same thing as the standard C preprocessor, since he speaks specifically of writing this preprocessor himself.

The C preprocessor is very limited. It can be used to make shorthands for common expressions, but that's about it. When you attempt to define new language constructs with it, it rapidly becomes more cumbersome and brittle.

Edmund
+1  A: 

I think Objective-C started out the same way. It was a preprocessor that built some C code that was then passed to a C compiler. But it was not THE C preprocessor in the sense of #define FOO, it ran as an additional step before or after the standard C preprocessor. The result of any number of preprocessor steps can then be sent to the C compiler.

drawnonward
+2  A: 

For an example of the kind of monstrosity of a "language" you can create using the C preprocessor, have a look at this header file:

http://www.bsdlover.cn/study/UnixTree/V7/usr/src/cmd/sh/mac.h.html

It's from the source code of the original Unix shell written by Steve Bourne and it aims to turn C into an Algol like language. Here is an example of what a piece of code looks like when using it:

http://www.bsdlover.cn/study/UnixTree/V7/usr/src/cmd/sh/args.c.html

That looks kind of bizarre but it is still C. It may look like a different language, but because it is implemented in the preprocessor, there's no syntactic support for it e.g.

WHILE foo
DO
    SWITCH
    ....
    ENDSW
OD

is all very fine and compiles nicely, but so does

WHILE foo
DO
    SWITCH
    ....
    OD
ENDSW
JeremyP