I was wondering why C++ is a good choice to write a compiler. Of course C is good for this purpose too, because many compilers are written either in C or C++ but I am more interested in C++ this time. Any good reasons ? I was looking for that in the Internet, but I cannot find any good reasons.
-
3"Many compilers are written [...] in C++" - any references? Which ones? What makes you think C++ is more often used for compiler construction than other popular languages?– Doc BrownMay 26, 2012 at 5:41
-
7@DocBrown Well, Clang and MSVC are written mostly in C++, gcc have a bit of C++ in it now, Java JVM are written in C++ stackoverflow.com/questions/410320/what-is-java-written-in and also superuser.com/questions/136136/…– KlaimMay 26, 2012 at 7:52
-
@DocBrown DMD the reference compiler for D is written in C++– ratchet freakMay 26, 2012 at 17:36
-
3Who says it's a good choice??– PhilMay 26, 2012 at 19:45
-
2@Phil Do you think they made this choice without any consideration of alternatives? It's not a "good" choice, it's a "efficient" choice.– KlaimMay 27, 2012 at 11:34
8 Answers
C++ has two sides to it. It has a low-level development side which makes it seem like a natural language for doing low level thing like code generation. It also has a high-level side (which C does not) that lets you structure a complex application (like a compiler) in a logical, object oriented way, while still maintaining performance. Because it has both the low and high level aspects to it, it's a good choice for large application which require low-level features or performance.
-
11As far as I know a lot of the logic inside a compiler is of functional nature (transforming complex data structures into other data structures) so I am not sure if object-oriented facilities (which are more targeted to programming-in-the-large, architectural aspects) bring a real advantage to compiler construction wrt to a procedural programming style. Just my 2 cents.– GiorgioMay 26, 2012 at 5:36
-
6@Giorgio Having objects helps in a lot of other aspects of compiler writing. For example, there's a lot of state a compiler has to deal with when optimizing and that kind of stuff lends itself well to OOP. Also, OOP and Functional programming can be quite complimentary, so just because the algorithms might be mostly functional, doesn't mean that objects won't help.– OleksiMay 26, 2012 at 5:39
-
4@Giorgio and Oleksi: I can confirm both of you. I wrote a compiler with Haskell for a real world language. It was a really good fit. But sometimes I missed some OO around. If I had to write another compiler I'd definitely choose Haskell, but this is really a special case. I would not choose Haskell without hesitation for other types of projects. May 26, 2012 at 7:19
-
28Why do you need to have a language with a "low-level side" to do code generation? I can't see how these two are connected in any way.– phant0mMay 26, 2012 at 8:52
-
6You don't need a "low-level side" to do code generation any more than you need Unicode identifiers to be able to write Japanese text to a file.– dan04May 26, 2012 at 16:05
My experience does not agree with your premise here. In fact, for high-level general-purpose languages, it is a very common practice to write the compiler in the same language as the source language (the language being compiled). For example:
- Sun's Java compiler is written in Java
- The Scala compiler is written in Scala
- Mono's C# compiler is written in C#
- Squick's Smalltalk compiler is written in Smalltalk
- ... and many more
An exception is compiler front-ends written for existing compiler frameworks, such as GCC, LLVM or Polyglot, which are then written in the framework's language, or compilers that rely on existing parser generators such as Yacc. Since GCC, LLVM and Yacc are common, established tools written in C and C++, it gives an incentive to compiler writers to use them, which might lead to C and C++ getting a large share in the compiler implementation language distribution.
-
2I think that has much more to do with the people writing the compiler knowing well and liking a lot the language they are writing a compiler for than for objective technical reasons. May 26, 2012 at 18:40
-
1@Krelp I agree it's not about an objective technical reason, but it's not really "liking", either - it's just considered some rite of passage for a language - "is it mature enough to be able to serve as the implementation language of its own compiler".– OakMay 26, 2012 at 18:44
-
1Sun's Java compiler is written in C++: stackoverflow.com/questions/410320/what-is-java-written-in– KlaimMay 27, 2012 at 11:36
-
12@Klaim you are confusing two products here. One is Sun's Java compiler (
javac
command-line), which compiles Java to Java Bytecode. It is written in Java - I have modified it many times myself and you can browse its Java sources online. The other is the just-in-time compiler embedded in the Hotspot JVM, which compiles Java Bytecode to native machine code. Like most of the JVM it's written in C++, but it's not a Java compiler - in fact, it knows nothing about the Java language.– OakMay 27, 2012 at 12:17 -
To compile what to what? A compiler transforms a source code from one language (source language) to another (destination language), which doesn't indicate anything about the low-levelness of the destination language.
- CoffeeScript compiles to JavaScript, the compiler being written in CoffeeScript.
- Script# compiles C# into JavaScript, the compiler being written in, if I remember well, C#.
- etc.
The language you pick to write a compiler depends on the context. For example, working on a project which compiles a language derived from PHP to a native PHP code, I used a mix of PHP and C# to write the compiler, because it made the most sense for me given my skills. Another person would pick Python, or Java and PHP, or C++ with a bit of JavaScript, or whatsoever.
C or C++ is a popular choice because of the support of compiler related tools (see the answer by Telastyn), and because those two languages allow you to go really native. But there is nothing wrong in choosing another language.
Note that in order to be more geeky, you may pick the source language to write the compiler itself. It's what happened for CoffeeScript compiler and many other compilers. It is also popular with the IDEs: one of the first Visual Studio was built using the same Visual Studio.
-
5Self-hosting is not geeky, it is an important property for porting a compiler.– user1249May 26, 2012 at 8:49
-
5The reason is, that it immediately enables the compiler itself to be a test program. It will most likely also be the largest program for that compiler for quite a while.– user1249May 26, 2012 at 10:27
I tend to question the basic premise here. While C and C++ work perfectly well for writing compilers, quite a few other languages seem to work perfectly well for the task as well.
A bit depends on the language you're compiling though. For small, simple languages, C and Pascal work quite nicely. If you're going to compile something big and complex, your compiler gets big and complex too -- in which case, C++'s extra features for organizing and working with larger programs obviously come in handy. That isn't really very specific to compiling though, just features useful for larger programs in general.
I think it's also worth mentioning one other point. Beginners (seem to) think of compilers as mostly doing text manipulation, so they think something like Perl will be a massive help in writing compilers. In reality, most of the interesting parts of compilation don't really start until after you've built your AST. While I'm sure Perl can do the job perfectly well, its text manipulation capability doesn't really give it a huge advantage either (text manipulation is mostly in the lexer, and lexer generators for things like C all support REs anyway).
-
3
Compilers may be implemented in any modern language. However, one of the most important requirements from a compiler is to be fast.
C++ has a clear advantage here. Optimization in C++ does not come cheap. However, due the the low-level nature of this language, it is possible to manually optimize C++ code more than in any other language (except Assembly which is not portable).
-
11Another important requirement is for the code generated to be correct - I'd rather have a slow compiler I can trust than a fast one which generates incorrect code.– user1249May 26, 2012 at 10:24
-
2While it is certainly possible to optimize C++ very heavily, there's a lot of rather… well… less than optimal C++ code out there. May 26, 2012 at 18:29
-
2@DonalFellows Turn it the other way around: it is possible to write less than optimal code in any language, but there are optimizations that are impossible to enable in other languages than C++ (other than Assembler. I don't include C because of lack of high level structures allowing stronger inlining).– KlaimMay 27, 2012 at 15:30
-
@user1249 - There is no reason that the speed of C++ code would make it any ore buggy. I'd rather have a fast, correct compiler than a slow, correct compiler. Jan 30, 2020 at 19:07
I suspect that the prime motivator for their use is that Lex/Yacc/Bison output is (primarily) in C. Since that's been the standard for so long, it has momentum.
Not that those are particularly good reasons...
-
-
That does not answer the question "why to choose C++ over C for compiler construction". May 26, 2012 at 5:43
-
3It's not a good reason at all. Analogous tools to Lex and Yacc exist for many platforms. PLY and ANTLR, for example. May 26, 2012 at 5:58
-
Moreover, most popular real-world compilers (I'm pretty certain abuot Clang and GCC, for instance) use hand-written parsers.– user7043May 26, 2012 at 8:55
-
@delnan: Yes but they probably started off using a generated one to get things off the ground. The hand generation of the parser is an optimization step you don't really want to do until you can prove other things are working. May 27, 2012 at 1:43
I have experience with this matter. I have written compilers in C and C++. The main difference between C and C++ is that C does not have dynamic memory management in an automatic way. All memory management in C has to be done explicitly. Writting a compiler deals a lot with string processing and array management. In C you are forced to think about the size of every string and every array you declare and also check indexes when you access those objects (if you want your code to be safe and stable). In C you can have dynamic memory management, of course, but nothing is automatic. You have to explicitly allocate and free memory using malloc() and free(), keep the size of your dynamic objects in separated variables in order to be sure you do not access them out of boundaries.
In C++ you can have the same mechanisms but it is really development time efficient because all your memory management can be encapsulated within constructors and destructors which you do not have to call explicitly. So the compiler is allocating and freeing resources for you. The size of your dynamic objects can be encapsulated as well if you create your own classes, and indexes can be checked for boundary access by overloading operator []. These abstractions help to make your code cleaner, easier to understand and debug and makes definitely development faster.
If you create a compiler in C it will take you more time for sure. C++ will make you finish your project in less time. C and C++ have same performance but C++ has a lot of advantages that C does not have.
The CompCert project is a research C compiler which is not written in C or in C++, but more in Ocaml and Coq.
Observe that C++ used to be translated to C (in Cfront). Now you may use the GCC front-end to Gimple, then dump the Gimple to some database, then write a Gimple to your assembler translator. But legal reasons (the GCC runtime library exception) requires such a compiler to be open source. Ask your lawyer for details, I am not a lawyer. Old variants of GCC have been written in C (+ several domain specific languages) with a front-end for some variant of C++. OpenWatcom could be a C++ compiler written in C (I leave you to check that).
The source of Compcert are freely available for academic and research purposes. If you want to use it industrially (and legally), you need to get some license from Absint.
See also this and that answers to two related questions.
If I was tasked in 2020 to write a C (or C++) compiler from scratch (running on Linux, maybe some cross-compiler) I probably won't write it in C++. I would consider writing it using Ocaml, Go, or Rust. And I could base it on Frama-C if so allowed. If required to code in C or C++ I would first code a garbage collector library for it, probably some persistence layer -very useful for whole program optimization- and then I would consider a metaprogramming approach (generating most of the C or C++ code of the compiler with my ad-hoc tools, maybe Bismon or RefPerSys if so allowed).
You could find some (more or less open source) C compilers coded in Common Lisp or in Python (e.g. ShivyC or nqcc). Look also into ZetaC.
Notice that recent versions of GCC are technically not coded in pure C++, they are a dozen of domain specific languages involved in GCC (several of them being Turing-complete). See also my old GCC MELT project.
I won't be surprised if, in future versions of GCC, some Python or Guile interpreter would be embedded inside them (for example, as a replacement for the pass manager of GCC).
Look also into the MILEPOST GCC project.