Reorganize layers to introduce the translation workflow right at the start.
We also avoid duplicating parsing code. Programs are always parsed into
the `program` data structure.
Let's minimize the alignment requirements of each segment's offset.
It'll make binaries take less room later. Otherwise we may need to pad
lots of 0s for segments after the first.
Generated ELF binaries continue to work natively (except ex4, but that
was already not working).
Return to the usual whitespace-skipping istreams. No need to go beyond
word-based parsing.
This exercise reinforces the amount of duplication between
load_program() and transform_immediate().
ex4 now writes to the (global) data segment, rather than trying to write
to the code segment.
We still need to specify the other segments in the generated ELF,
though.
Drop a safety net; we now assume that Memory is large enough for any
addresses we may encounter.
Dropping all comparisons with Mem.size() now makes our Memory_offset
indirection airtight.
Modify helpers to run either external examples in the subx/teensy/
directory, or my own examples in subx/ directory.
Now I have to say `run test5` instead of `run 5`, and so on.
Second attempt at commit 4291. We'll now not copy the headers into
memory, but we'll still allocate space for them. Still some security
benefits, and I'm gaining confidence that I understand the ELF format.
Learning to use the data segment.
Currently, subx can only run the teensy files generated from flat
assembler:
test4
test5
test7
This is not a priority to fix. These files are just useful references to
have around.
Doesn't compile.
I'm still not sure how to represent types and global variables.
Types won't be in the final binary.
But globals will. Perhaps I should first figure out what that looks like.