P.S. We're the Visual Basic compiler too :)
P.S. We're the Visual Basic compiler too :)
Man, this is a crazy world. Cats and dogs living together. Open source MS projects. The falcon cannot hear the falconer
This is basically old hat for me -- I'm just glad Microsoft agrees it's the way to go. :)
We're looking at a lowered on-ramp to .net apps that run more smoothly than java+linux+every-support-tool-bit (dev-wise) across devices (and things). It's compelling.
Everything from dev to deployment and ops is getting touched at this conf. This shows where MS's strengths can present differentiation. Their profit source is, and has been, building/selling tools and platforms for others to run businesses. When the thing people hate becomes more like what they aspire to have/be, the tension is palpable.
Google is about the only other player nearly capable. But Google's mission has far less to do with selling shovels vs. harvesting and monetizing.
Apple is just not in this space. If anything, they sure feel like a device-only company in this conversation. WWDC is about the garden. Build is handing out spades, shovels, and, now, dirt.
Xamarin's Evolve, last year, felt a bit like all this does. The are big things happening. If nothing else, at least it feels like change, if not progress for devs and consumers.
The garbage collector for example would be very interesting to peruse. Sure threading and synchronization code would be differ but these have been emulated on Linux before to good effect, I don't see any serious barriers there.
I'm sure the codebase is factored internally to have some sort of platform abstraction.
Interestingly, no -- but neither can the native C# compiler (that's what we call the old C# compiler that everyone's using in VS right now)!
Why? The C# compiler is bootstrapped, so we actually compile the compiler with the compiler. It just so happens that a while ago we felt we needed a feature so badly for the C# compiler that we introduced it into the C# language (exception filters) and started using it in the compiler immediately. So in order to compile the compiler, you need a C# compiler that supports exception filters, which right now is just the Roslyn C# compiler. Honestly, the feature (and some other small changes we've made) aren't that complicated, so they could be backported to other compilers, but I don't know why you would want to do that.
A few years ago I was on a small team working on a .NET compiler and runtime -- it compiled MSIL into native code targeting x86 and PowerPC. I remember when working on the part of the compiler that built the exception handling routines running into exception filters and wondering what they were for. We were largely targeting C# as a development environment at the time but ended up implementing them in case anyone wanted to use VB.NET. Funny to see that they're now making their way back into C#, even if it's just in the compiler :)
This isn't just useful for the compiler, but we felt it was necessary for us to make the most reliable, agile product.
Then they wrote the second C# compiler in C#, and used the first compiler to compile the second compiler. Voila!
This source release is so cool!
We only stopped bootstrapping using the native compiler about, oh, 6 months ago, since that was when we decided to take a dependency on new language features. The next VS will be the first VS where Roslyn is the default C# compiler.
Bootstrapping a compiler from nothing is harder and involves a lot of incremental steps. http://en.wikipedia.org/wiki/Bootstrapping_(compilers)
http://c2.com/cgi/wiki?StructureAndInterpretationOfComputerP...
And tends to happen to other languages... you just have to bootstrap the first compiler.
Some other interesting contemporary examples:
I think as we speak Go is working on its plan to switch from using a compiler written in Go[2].
Rust[3] has kind of a hybrid approach where the front-end of the compiler is written in rust, but generates llvm bytecode which is then compiled the rest of the way by llvm itself. It takes three "stages" for them to do a full compile, first a binary "snapshot" compiler is downloaded and used to compile the compiler (stage 0), then that generated compiler is used to compile the compiler again (stage 1), and then that generated compiler is used to compile the compiler again (stage 2). Stage 2 is actually just a test - its output should be identical to that of stage 1, and if it isn't, something went wrong.
There is a classic lecture from Ken Thompson[4] that I think is really illuminating on how this stuff works, if you're unfamiliar with it.
It's really fascinating stuff!
[1]: http://homepage.ntlworld.com/edmund.grimley-evans/bcompiler.... [2]: https://docs.google.com/document/d/1P3BLR31VA8cvLJLfMibSuTdw... [3]: http://www.rust-lang.org/ [4]: http://cm.bell-labs.com/who/ken/trust.html
If you already have a compiler in the language you're compiling, you can update the compiler with new features by the following process, called "bootstrapping". This process is used in gcc for example:
1. Use the old binary version to compile the new source version.
2. Use the binary produced in step 1 to compile the new source version.
3. Use the binary provided in step 2 to compile the new source version.
The results of stages 2 and 3 should be the same (assuming the old and new compilers assign the same semantics to the compiler source code and don't have non-determinism, e.g. using wall-clock time to determine when to stop searching for optimizations).
The bootstrap process can't be used on the first compiler for a brand-new language, because there is no "old compiler" that can be used in stage 1. The only way around this is to write the first compiler in a different language that already exists.
Of course, if a self-hosted compiler is your goal, you can afford letting the very first compiler (the one written in another language) be limited, "dirty," or "hacky". You don't have to implement the entire language in the first compiler; the first compiler just has to support enough of the new language to allow you to write the second compiler.
Anyway, once you have the first compiler, you write the first version of the second compiler in whatever subset of the language the first compiler supports. Once the first compiler builds the first version of the second compiler, the first compiler is no longer needed; you can add all new features to the second compiler only.
New versions of the second compiler (perhaps supporting more language features) can now be produced by bootstrapping. Of course, you can also use the second compiler to compile a totally different compiler implementation written in the new language (this would be the third compiler for the new language).
Lots of people use it
It's also somehow satisfying to witness Xamarin's success and further opening of .NET after all the bashing and hating Mono received from the free software community.
Now that MS has released the stuff under Apache license things have really changed.