revivalizer/compilertalk — pull request #1 by schierlm (2013-04-01 16:18:11+00:00)
Title: Fix compilation of VM with MinGW, and fix unary minus in lesson 02/03

Also add a TEST_MODE to the VM that takes hex bytecode on command line, and add an test_integration.lua that calls this for doing some integration tests (compile an expression, run the bytecode and run the result).

This is only done for lessons 01-03, as in lesson 04 there is a syntax error in the lua code, so I stopped looking more closely at that one.

The main reason why I had a look anyway was because I wanted to see why the "common" way of fixing associativity in EBNF (having a rule like `additive <- additive '-' multitive`) does not work. Seems that parser generators that cannot cope with left recursion in the production rules still exist. (Yes I know that `LL(1)` and `recursive descent` parsers cannot cope with direct left recursion, but the way to remove it by adding another nonterminal symbol (and automatically removing it from the parse tree afterwards) is oold so I though people had already implemented that. (Even yacc and javacc handle that case better...).

(PS: As I'm an advocate of strongly typed languages instead of "stringly" typed languages, I may try to implement the latest version in Java + JavaCC just to see how it compares. While it will most likely be more code, I guess due to better IDE support it may be less code to type, and the AST will be strongly typed and so be more maintainable. Usually advocates of dynamic languages say that static typing does not matter as unit testing is easier in dynamic languages. Yes, that's true, but being easier does not mean that you are automatically doing it...)

(PPS: Great talk. While I don't have a PhD, I have attended a compiler construction lesson when I was at university, and I think you've done a great job boiling it down to one hour of time. What I'd have added is comments (one of the more important language features in my opinion) and maybe dynamically scoped locals (like `local(x=9) { y = x * x;}`. Not hard to implement in a stack based VM (push the old value at beginning of block and pop/restore at end) and a good starting point for the other important language feature that makes reuse possible: procedures and functions. (And yes, I agree too that implementing lexically scoped local variables is a PITA, especially if you have code blocks that can be called recursively (requiring both static renaming in the parse tree and allocating some kind of stack frame for storing the variables), but dynamically scoped locals are usually "easy"))

(PPPS: Sorry for messing up this pull request with so much unrelated details...)