diff options
Diffstat (limited to 'interpret.e')
| -rw-r--r-- | interpret.e | 60 |
1 files changed, 56 insertions, 4 deletions
diff --git a/interpret.e b/interpret.e index f45a1c5..7db86b7 100644 --- a/interpret.e +++ b/interpret.e @@ -36,7 +36,7 @@ ~ At any rate, the code in this file is responsible for that compilation. ~ ~ It is primarily concerned with managing the contents of an area of memory -~ we call the "log". Traditional Forth TODO +~ we call the "log"; see log-load.e for more detail on terminology. ~ TODO find a better place for this : describe-compilation @@ -50,6 +50,7 @@ ." name of latest: " latest @ entry-to-name emitstring newline newline ; + ~ Allocate space by incrementing "here", and output a word entry header in ~ it. Also add it to the "latest" linked list. Use zero as the flag values; ~ accept a string pointer on the stack and use its contents as the name. @@ -130,9 +131,18 @@ ~ (value to append to current word-in-progress --) : , here @ swap pack64 here ! ; + : self-codeword here @ 8 + , ; -~ (address for new variable word to create, name string --) + +~ A variable is simply a word that returns a specific address, always the +~ same one, at which a value can be stored. This word "variable" takes and +~ address and a word name, and defines the word. Allocating space is its +~ caller's responsibility. +~ +~ TODO the address is constant but the contents vary, confusing, write it up +~ +~ (address for new variable word to point to, string pointer --) : variable create self-codeword @@ -143,6 +153,49 @@ 8 packalign here ! ; + +~ A keyword is a word that evaluates to its own address, which makes it +~ suitable for use as a constant. By convention, all our keywords have names +~ starting with a colon, which imitates the way they work in Common Lisp. +~ +~ Specifically, it returns its own execution token. Thus, executing its +~ result repeatedly will keep giving the same value. We aren't in the habit of +~ doing quote-exec kinds of things in Evocation, but it seems as good as any +~ other unique value, so we might as well. +~ +~ Unlike CL, we don't currently have the lexer automatically create keywords +~ for us; we create them explicitly. That's likely to be added at some point, +~ but at the moment the feature is lying fallow to see whether it winds up +~ seeing a lot of use. +~ +~ (string pointer --) +: keyword + create + + ~ Before outputting our codeword, save a copy of the address where it's + ~ going to be. That will be the execution token we return. + here @ dup + ~ (self execution token, output point) + + ~ Now add a codeword. This is an assembly word, so it's a self-codeword, + ~ meaning it points to the word right after itself. + dup 8 + pack64 + ~ (self execution token, output point) + + ~ Now we consume the execution token, using it as part of this instruction. + :rax mov-reg64-imm64 + ~ (output point) + + ~ To return it, we push it to the stack. + :rax push-reg64 + + ~ Now just the normal stuff every assembly word ends with. + pack-next + 8 packalign + + here ! ; + + ~ Allocates bytes on the heap by incrementing the global "here" pointer. The ~ "here" pointer is kept aligned to an 8-byte boundary, regardless of the size ~ requested. @@ -235,8 +288,7 @@ ~ Sets the backing store of an input buffer to point at a null-teriminated ~ string and read from it. ~ -~ TODO are these backwards -~ (string pointer, pointer to buffer metadata --) +~ (buffer metadata pointer, string pointer --) : attach-string-to-input-buffer swap ~ (string pointer, metadata pointer) |