21 comments

[ 6.8 ms ] story [ 53.2 ms ] thread
Javascript for a compiler course? That seems like a very unusual choice. Good luck to you!
Thanks! Yes, we use JavaScript as the most popular language, however the code should be easily portable to any other language.

The multi-paradigm nature of JS, with its first-class functions, closures, static scope semantics, class-based and prototype-based inheritance fits the best to study semantics of programming languages -- and all these concepts we implement in the course.

For low-level bytecode interpreter there will be a C++ implementation.

IMHO what is essential as a language feature for writing interpreters/compilers is algebraic data types and pattern matching on them, because they make things much easier when manipulating ASTs, which is a frequent task in implementing these programs.

Unfortunately besides functional programming languages (Haskell, OCaml, etc) or modern languages (such as Rust), there are few having these features, and JavaScript is no exception. Of course you can use a poor man's substitute such as the Visitor pattern, but it's quite a hassle without a direct language support.

Yes, good point on pattern matching and algebraic data types (initially I was actually considering Rust for implementation, but not OCaml). The visitor pattern is a classic though, and is transferable knowledge further, to process different kinds of graphs, trees, etc. BTW, JavaScript will likely be getting pattern matching soon as well.
The great thing about compilers is they're conceptually pure functions - take an array of characters as input and produce an array of bytes as output. You can do that in any general-purpose language - high level, low level, old, new, whatever, you don't even need any libraries - it's all just numbers in and numbers out! So yeah pick whatever you want. Algebraic and object-oriented languages seem to work well in practice as the problems are data-structure-intensive, but many other paradigms also work well. I really love compilers, I think they're the perfect program.
> The great thing about compilers is they're conceptually pure functions - take an array of characters as input and produce an array of bytes as output.

While this is undoubtedly strictly true, it seems so high-level that the same could be said of essentially any programming task, with I/O suitably modelled, and so gets awfully close to "the C language is purely functional" (http://conal.net/blog/posts/the-c-language-is-purely-functio...).

My friends who work on web services have to send out tens of requests to other services to get anything done. So their request handlers aren’t pure functions.

People think about compilers as being systems code but it’s the opposite. It’s the web and business code that’s a nest of state and dependencies on systems.

Compilers are just numbers in numbers out.

I’ve been writing all my language runtimes and compilers in TypeScript lately, mainly because they also have web UIs. It really isn’t that bad.
There seems to be a real cottage industry of how-to-write-interpreters/compilers at the moment - Writing an Interpreter/Compiler in Go, Crafting Interpreters, this, etc.
Yes, I agree, the topic is becoming pretty hot these days, and this reflects the era of transpilers, WebAssembly, coming into play with its nested bytecode format, and other related topics. More people are getting interested in how things work under the hood, instead of just "using" a language.
Hey, I enrolled in your previous Udemy course about garbage collection last year and while I did not yet finish watching all of the videos I did watch quite a few of them.

So first of all, thank you for creating that course about garbage collection. The videos that I've watched from it so far were interesting and informative to me. (I've completed 71% according to Udemy but I must admit that I sometimes watched videos as I was going to bed and may not have been fully attentive at all times.)

Secondly, a small suggestion for improvement based on the first course: Since each piece is relatively short, it quickly becomes quite tiring that each and every video begins with a ~15 second long intro animation, most of which is just repeating the title of the course. I would skip that all together and make the transition 2 seconds long at most. Just enough to read what the topic of the current video is.

Thanks for your feedback, appreciated! And glad the Garbage Collectors class is interesting. Yes, I'll consider shortening the intro in the future classes. Initially each lecture was a self-contained, and potentially with no related context to previous lectures, however when combined in a class, yes, it makes sense to make the intro shorter. In the Interpreters class I shortened it to ~5 secs only.
Absolutely, and it's fantastic! It's the most fun I've had with my computer since my first "Hello world".
I think it's people realising that compilers aren't that complicated until you get into the backend.

Lots of optimization passes, even, are relatively obvious (not necessarily trivial, but they make sense) - to my eye at least, the Voodoo magic is in the scheduling and code generation

With something like the dynamic language runtime, even code generation can be easy. Too bad it hasn’t been copied on other platforms outside of .NET.
What does .NET do to make code generation easy?
The DLR as I mentioned is an API for dynamic code generation that hooks into the platform’s JIT. The code you can generate with it runs fairly fast (as fast as other JITTed code)
Do you mean just generating bytecode through an API? That's a completely trivial problem in the first place - just linearise your AST. When people talk about 'code generation' they mean the complexity of native instruction scheduling and selection.

And if you want to just generate byetecode doesn't Truffle on Java do that far better than DLR? Truffle seemed to actually achieve what DLR promised but never really managed - genuine support for dynamic languages on .NET/JVM.

The DLR had two parts: support for dynamic languages, and a strongly typed API for generating expression trees at run time. The second component is the one that survived and is fairly robust. It is quick, skipping the bytecode stage completely, and is fully typed.
> the Voodoo magic is in the scheduling and code generation

Yes, for the code generation one needs to well understand semantics of the target language. And when it's a low-level language (Assembly), the "voodoo magic" mainly relates to generic understanding of the lower-level architectures. However, there might be compilation to another high-level language (in case of a transpiler), and by itself code generation at this stage is not that hard, simply because a target language is more understood in this case.

Instruction selection topic, and where to place the data -- on the stack, or into registers (and how a register allocator works) also mainly relates to the lower-level.

> until you get into the backend

Yes, and that's why I think it should be a separate class, specifically for higher-level compilation, and a low-level compilation.

We'll be covering this in "Essentials of Compilation".