*********************************************************** * Meow5 Design Notes * *********************************************************** All this stuff is pretty much done - but I'm leaving this file for posterity. =========================================================== DONE: write header AFTER the word (to make it dirt-simple to calc length of machine instructions and write it there) DONE: use linked list like i learned how to implement in jonesforth =========================================================== DONE: Add a regression test suite to test all functionality as I add it (probably best added after I make this take input from STDIN!) (I have a very small test.sh - works great) =========================================================== Display free memory and bytes compiled so far - on start up and/or on demand. =========================================================== DONE: get as quickly as possible to : meow5 meow meow meow meow meow ; first compound word after meow5 could be: : exit0 0 exit ; =========================================================== Idea: Add description/usage instructions strings to word 'tails' so they can be read (maybe even searched?) while in the interpreter. A totally easy feature that wouldn't have made sense on the old memory-started machines of the late 1960s. I'm thinking that some stack annotations could be semi-automated, too. Well, there is a ton of low-hanging usability fruit once you go down this avenue. Gotta stick with the minimum viable PoC for now...would be so easy to get wrapped up in shaving those yaks and choosing juuuuuust the right colors for that bike shed... Also consider automatically generating the "stack effect" comments that explain the input and output params on the stack. (*Also* consider (optionally) enforcing them!) =========================================================== DONE/YES: A rule: COMPILE mode words can _only_ be defined via 'colon' OR composed entirely of machine code with no CALLWORD macros? =========================================================== DONE: Challenge: how to have dictionary words that can be called in meow5 itself to form the basis of the language (specifically, 'find', 'inline', etc.)? The "tails" that make them words make them not function as good assembly citizens. Right now, I've got a temporary variable in BSS that functions as a single return address for these words. What I think I might need to do is make a macro that detects that a return is requested and then does it. DONE: Yup, went with this idea: OR have two labels at the end of those words - one that is the end when you inline/compile it as a word and the 'tail' label. The length of the word would be considered the instructions before the "return" jump mechanism. So when inlined, it wouldn't even check for a jump, it would just flow on through to the next word. DONE: And I think i'll probably need to have a mini-stack for return addresses in this tiny subset of words-that-can-be-called-like-functions. Just a handful of nested calls (i'm not going to use recursion or anything like that): return_stack: resb 32 return_stack_pointer: resb 4 Something like that. NOTE: Turns out, an "inline all the things!" language can't have nested calls anyway (kinda obvious in retrospect) so I'm removing the return stack and replacing it with my original single return address. This is only used in immediate mode to return from a single word's immidate exection. =========================================================== Display machine code (at least) and all 'tail' meta-info about a word (or all words), maybe even with some nice ansi color coding. I wanna make this look pretty so much, but I know I've gotta hold off on the curtains and carpet and get the walls and floors built first.. =========================================================== DONE: have explicit interpret-time vs comp-time context words. Regular interpret-time: : foo 1 2 add ; Compile-time: :comp if ... ; And when searching, we can skip any words that don't match: * name length * name * context (compile or interpret) Which ALSO means that we can define two different words with the same name for compile/run (or interp/comp) time =========================================================== DONE: Use stack for all word param passing - don't get fancy with trying to keep track of registers with this proof of concept!!! =========================================================== DONE!!!! How hard is it to write an elf executable? it would be super cool to be able to write any compiled word straight to disk as a tiny, self-contained executable! Especially when done right from the interpreter REPL. I bet not many languages have *that* feature! (I don't know of any). =========================================================== DONE!!!!! And holy cow, that was rough. Done? As long as we have free space for them, strings have a place in memory now... Challenge: Programs are built up by concatenating words togeher, so by definition, everything a top-level word needs is guaranteed to be contained in that word (if we wanted to write it out as a stand-alone executable.) But how do we reference data like strings? And variables/constants? How do other compiling Forths handle that, for that matter? Do they write out every word in the dictionary? And is the outer interpreter always included??? =========================================================== Register Usage Typical usage notes (JF = JONESFORTH) EAX: The accumulator/return val EBX: often for pointers ECX: often for counters EDX: whatever ESI: The source index for string operations. JF used ESI for NEXT word address pointer EDI: The destination index for string operations. EBP: pointer to current fn stack frame base JF used EBP as Return stack pointer ("RSP") ESP: pointer to current fn stack frame top JF used the stack as THE parameter stack EIP: instruction pointer! =========================================================== DONE: Hmmm... as much as possible, I'll use the stack and other in-memory pointers to avoid having to think about explicit registers as much as possible. Certainly some of the ones needed for a traditional "threaded interpreted" Forth won't be needed for Meow5!