Replace the map with a hash table that should be faster.
Dead code elimination.
I'm playing with fire not doing any register allocation, but this works for now.
It's not the best register allocation routine, but it works pretty good so far.
Operator precedence parsing and the addition operator.
Multiplication operator.
Fix the operator precedence while loop so it correctly generates left-associative expressions.
Subtract and divide operators. Update the optimizer so that it allows constants with the values ~0 and ~0-1. Move bytecode emit to its own procedure.
Don't need this anymore.
A bunch of test cases, some fixes to some bugs they uncovered, and a reworking of assignment.
Me changing around how the parsing works so that multiple global level things can be supported.
Starting to add calling other procedures. Code emit doesn't work yet but parsing does.
More code to call other functions. Still not done. This is a lot of work. Includes some improved ast checking and call graph analyzing to remove unused procedures. Some tests fail, I commit this code because I want to rework the IR.
Rewrite 3ac registers so that there's no reserved register anymore, return receives a parameter and call writes to its dest register. Should allow for simpler optimization procedures.
Get tests passing again.
Finally fully implemented call instruction relocation.
* fix incorrect return value for scope_find, it should return an ast index
* fix incorrect looking up the wrong ast index in analyze_call_graph
* add/fix emit instructions for add/call/return
* add a copy instruction that copies the value of one register to another

All test cases pass.
Some more tests
If a variable 'a' is last read at the same instruction that a variable 'b' is first written then the two can share a register. This allows for some other optimizations down the line, avoiding extra copy instructions when building to x86-style two parameter opcodes. Awesome!