TMI: Elbows-deep in codegen
Oct. 31st, 2012 09:57 pmI've been immersed in some painful bug-fixing, and it hasn't seemed very appealing to write about it. First, while bug triaging, I found this issue from almost a year ago. As a solution, Graydon suggested changing the AST to preserve any parentheses that existed in the source code. This isn't as weird an idea as it seems as first: we also retain things like comments, so that we can test that our pretty-printer prints out the same code it was given. The pretty-printer had heuristics for deciding what expressions to parenthesize, but it was wrong in some cases and there were some tests where the pretty-printer doesn't roundtrip correctly (normally, we check that the pretty-printer roundtrips on every test cases). I implemented Graydon's suggestion, and as a result, all those heuristics are gone, which is satisfying. I thought this was going to be a quick fix, but it was actually difficult to get all the various bits and pieces of data stored in various hash tables that get passed around the compiler right. That is, if e has some entry in some table, should it also be attached to (e)?
Now I'm working on refactoring the code in trans that handles pattern matches so we don't have two different code paths doing the same thing: one for irrefutable patterns in let statements, and one for all patterns (including irrefutable ones) in match expressions. This has been mind-bendingly hard and is making me feel totally ineffectual. Part of the problem is that due to whatever weird psychological hangup of my own, I don't like to make small test cases to isolate bugs, so for quite a while I was trying to narrow down bugs as they manifested themselves in building the compiler itself. I finally gave in and made a stand-alone test case, which makes things easier... up to a point, anyway. My least favorite bugs are those that manifest themselves as bugs in generated code. I think we're doing well if most compiler bugs manifest themselves as assertion failures in the compiler. That happens sometimes now, but not always. As I told a co-worker today, though, the past couple days at work have just made me feel like a monkey with a keyboard (well, more so than usual).
What I should be working on is making labeled breaks and continues work inside for loop bodies, but this seems to require more understanding of trans than I have, and so I've been putting it off.
Now I'm working on refactoring the code in trans that handles pattern matches so we don't have two different code paths doing the same thing: one for irrefutable patterns in let statements, and one for all patterns (including irrefutable ones) in match expressions. This has been mind-bendingly hard and is making me feel totally ineffectual. Part of the problem is that due to whatever weird psychological hangup of my own, I don't like to make small test cases to isolate bugs, so for quite a while I was trying to narrow down bugs as they manifested themselves in building the compiler itself. I finally gave in and made a stand-alone test case, which makes things easier... up to a point, anyway. My least favorite bugs are those that manifest themselves as bugs in generated code. I think we're doing well if most compiler bugs manifest themselves as assertion failures in the compiler. That happens sometimes now, but not always. As I told a co-worker today, though, the past couple days at work have just made me feel like a monkey with a keyboard (well, more so than usual).
What I should be working on is making labeled breaks and continues work inside for loop bodies, but this seems to require more understanding of trans than I have, and so I've been putting it off.