Currently failing at layer 54:
```
$ time ./translate 049memory_layout.subx 05[0-4]*.subx; ./subx run a.elf test
leaky-get-or-insert-slice: too many segments
```
Emulation is also damn slow. But running in native mode is fast.
Bugfix fourteen: we need different address computation logic for code vs
data labels.
It's really about different categories of instructions having different
address computation logic. This subtle distinction will make good error
messages hard. But that's a problem for later.
Now there's just one example program not translating.
Figured out what's going in with bug fourteen: displacement operands
aren't always used relative to the PC. Does this mean I need to track
instruction boundaries past pack? :'(
No, I just need different logic for labels in code vs data segments.
This was an interesting bug for reminding me of the difference between
the emulator-level trace and the application-level trace. The former has
1.5 million lines, while the latter has a dozen. Luckily, just dumping
the latter immediately made obvious what the issue was.
Though this experience does suggest some further ideas for debugging
tools:
slice trace by line and phase
slice trace by start and end label
debug UI for SubX translator
2D layout: rows = lines of code; columns = translator phases
each 'cell' in this layout contains a list of log lines
shows what came in, what was emitted
easily collapse any cell
These are domain-specific tools. Special-cased to the SubX translator
phases.
Bugfix thirteen: displacement calculations were wrong because current
offset was not being updated properly as words were being read and
emitted.
Now 10/12 example programs are translated correctly.
Bugfix ten: type error in `convert`. I was calling `rewind-stream` on a
`buffered-file`.
examples/ex1 is now just one nibble off the canonical.
I *have* found one missing feature in the self-hosted translator,
though: dquotes doesn't support newlines in strings, even though the C++
version does. dquotes parses them right, but the value initialized in
the data segment is wrong.
Bugfix eight: incorrect segment count in ELF header.
The generated examples/ex1 is still not right. But it has the second
segment now. Or almost all of it. Final byte is missing for some reason.
The result isn't an identical binary to before, and it segfaults when
run. But it's bugfix seven.
A couple of places where we make .subx files a little more strict:
a) All .subx files must define a data segment. Even if they have no
data.
b) All .subx files must define an `Entry` label for the binary to start
at. Earlier we used to default to the start of the code label. That's
not too hard to add; we'd just need to:
i) rename `get` to `get-or-abort`
ii) clone a third variant of `get-or-insert` called `get` that returns
null if the key is not found.
iii) use `get` rather than `get-or-abort` when looking up the `Entry`
label.
map of how far we've gotten by now (functions with '*' independently tested):
✓ compute-offsets*
✓ compute-addresses*
✓ emit-output
✓ emit-headers
✓ emit-elf-header
✓ emit-hex-array*
✓ first emit-elf-program-header-entry
✓ emit-hex-array*
? second emit-elf-program-header-entry
emit-hex-array*
emit-segments*