I have now written a #z80 machine code monitor for the #MailStation. The command set is very influenced by WozMon, but unlike #Woz I haven't managed to fit it in 256 bytes (yet...)
So now, in the strictest sense of the word, I have a #repl on this thing!
(While there was already a built-in hex editor, it was not suited to interactive use. A reboot was necessary to test changes, and it was restricted to writing dataflash, which has a limited number of write cycles.)
PsfMon, my #z80 machine code monitor, is now running on my real #MailStation!
I optimized it from its original size of 332 bytes to 255 bytes, snugly fitting in one 256 byte page of dataflash. The gui "terminal emulator" takes another 256 byte page. This provides a self contained 512 byte development tool.
Command set - similar to #WozMon:
8000 - View byte at address 8000
8010,801f - View 16 bytes at address 8010
,803f - View from next address (8020) to 803f
8040>de ad - Place bytes de ad starting at 8040
>be ef - Place bytes be ef next (at 8042)
8000r - Execute code at address 8000
Anyway, here it is displaying 128 bytes of its own code.
#MailStation #Forth has peculiar execution flow because of the event-driven environment it runs in. Forth's entry points are COLD (expected!) and ACCEPT (rather less expected). Forth so far has only one exit/yield point, also in ACCEPT, to await input provided from the gui textentry field.
Execution smoothly falls through from cold -> abort -> quit -> accept, with no "ret" along the way. (Even the "ret"-to-caller on line 42, the exit point, is tailcall optimized away by jumping to the final function rather than calling it.) It still feels transgressive to embrace unstructured-programming, even though it works great for "telescoping" routines that share an end.
When user input is received, execution picks back up on line 43. Finally, quit2 slams us unceremoniously into high-level threaded code, because by now we have set up enough interpreter state to run it.
A lot going on in this screenful of code. It's absolutely wild to implement an interpreter core without needing any conditional-branch instructions yet.
@psf do enough coding in raw machine language and you won't need pen and paper.
I coded straight to 6502 and 8085 hex in the Time Before Assemblers. Then I wrote an assembler and never looked back.
Mind you I knew someone who insisted on coding in hex editor straight to machine language. He really objected to changing to an assembler. His code was a mass of jump instructions patching in changes (because hex editor).
This is why god invented cross compilers.