This commit reimplements commit 6515 to happen during type-checking rather
than as early as possible. That way we naturally get a more informative
error message.
The desire captured by a test is often hard to verbalize, path-dependent
and more fertile for the future than its original impulse. On some level,
someone wanting to rip out features has to just ask for each scenario,
"what do I want to happen here?" And nobody's gonna do that. At best, somebody
may be trying to rip out some complex feature, and run into some collateral
damage around the edges that they have to inspect more closely. "Do I care
about preserving this behavior?"
The new failing test is now passing, and so is this manual test that had
been throwing a spurious error:
fn foo {
var a/eax: int <- copy 0
var b/ebx: int <- copy 0
{
var a1/eax: int <- copy 0
var b1/ebx: int <- copy a1
}
b <- copy a
}
However, factorial.mu is still throwing a spurious error.
Some history on this commit's fix: When I moved stack-location tracking
out of the parsing phase (commit 6116, Mar 10) I thoughtlessly moved block-depth
tracking as well. And the reason that happened: I'd somehow gotten by without
ever cleaning up vars from a block during parsing. For all my tests, this
is a troubling sign that I'm not testing enough.
The good news: clean-up-blocks works perfectly during parsing.
I was shifting bitfields around based on their width rather than the width
of the field to their right.
Kinda shocking that I haven't used the scale bits until now. I've been
generating code that uses them in mu.subx tests, but apparently I haven't
actually _run_ any such code before.
Defining a new var in a register based on a previous var in the same register.
Unfortunately I don't yet support such an instruction without getting into
arrays. Ideally I want `y <- add x, 1` to convert to the same code as `x
<- add x, 1` if `y` ends up in the same register. And so on. But I don't
yet have a way to specify "output same register as inout 1" in my `Primitives`
data structure.