Scheme Programming

I've finally got source code references for Picobit byte code. It's proved enormously frustrating. My first approach attached the original syntax references to the structs used in the AST. After I'd done all this, I found only 2/3 of the tests passed.

I made what seemed like a reasonable assumption: the front end uses lots of incomplete pattern matching on the structs. I'd tried to update all the patterns, but perhaps I missed some. I went back and replaced the front end approach with a dictionary from AST nodes to syntax.

The result was exactly the same!

This was worthwhile though: the pretty printing of the AST now matches in the original and new versions, so I can capture that and prove the front and is unchanged. I have a script which captures the AST and the assembler output for each test file. Now I can just run meld with the two output directories as arguments...

There's one instruction I'm just not emitting: goto-if-false. Turns out that's just because I'd factored out a method to deal with re-emitting those instructions, but it actually just didn't emit the new instruction. After that, a branch reduction optimisation needed fixing. Down to one unexplained error now.

Racket points out when pattern matches for structs have the wrong number of arguments, so my first change was perfectly safe. It was also better in an important way: it let me improve error reporting across the board: given an AST node I could report file and position. In the end I've gone with the first approach. I'll hand code the pretty printing of the AST when I next find I need it.

Most of the rest of my pain comes from the fact that Racket stack traces refer to the start of the top level closure, rather than the call site, which is pretty crap compared to what I'm used to (which is the JVM or CLR). The more nested closures the greater the frustration. Anyway, that's made me think I'd better have a rotating buffer of the the last N call sites in the picobit interpreter.

I'm really yet to work out if I can work around this using the Racket debugger.

The branch optimisation code I mentioned above used cadar which means the second item in the first list! When I encounter code like this it reduces my surprise that few people stick with scheme. I'm beginning to think if I get much further with this I'm going to invent a new language with a syntax for index refs.

I did all this to have some sort of debugging capability, but when I finished all my work on the compiler, the program I wanted to debug didn't crash any more, so I guess I inadvertently fixed a compiler bug. Certainly there are a lot more contracts and guards in the compiler, and I've just blindly fixed anything they complain about, but I can't see a fix in the diffs. I guess I'll have to go back and check.

Popular posts from this blog

3D Printer ramblings

Balance Bot V2

Robot arm