diff options
| author | Irene Knapp <ireneista@irenes.space> | 2026-05-20 19:59:18 -0700 |
|---|---|---|
| committer | Irene Knapp <ireneista@irenes.space> | 2026-05-20 20:03:01 -0700 |
| commit | 2fcfc1bcb59e0c1716a6a7dffcad4e0b90790a20 (patch) | |
| tree | 4ee37eaf51f26913170d062c14be29274b486618 | |
| parent | 53f52a67b7c5bb8af12c92a2f3a219e75dd9b0c3 (diff) | |
so yeah, docol, exit, and lit all work in log-load now
also s" and ." work in the label transform, and are used to produce an important error message during the log-load routine, since we can't know whether log-loaded words exist until runtime sweet, right? Change-Id: I6a67139538c2cbcef40a1093202b2b4e0ad6febb Force-Push: yes
| -rw-r--r-- | evoke.e | 10 | ||||
| -rw-r--r-- | execution.e | 16 | ||||
| -rw-r--r-- | log-load.e | 10 | ||||
| -rw-r--r-- | transform.e | 52 |
4 files changed, 79 insertions, 9 deletions
diff --git a/evoke.e b/evoke.e index 05e500e..1d545b1 100644 --- a/evoke.e +++ b/evoke.e @@ -39,12 +39,16 @@ here ! here ! ] ;asm ~ Now that we have exit, semicolon will also work and we can define -~ non-assembly words. -: foo 4 5 + ; +~ non-assembly words. However, it will be hard to make them do much until we +~ have lit as well. +: lit + [ here @ + lods64 + :rax push-reg64 + here ! ] ;asm 42 sys-exit - pyrzqxgl ~ 0 sys-exit s" source-to-copy-to-log" variable diff --git a/execution.e b/execution.e index c3f99f2..2c8b869 100644 --- a/execution.e +++ b/execution.e @@ -176,7 +176,15 @@ ~ pointer where we asked; we don't need to check what those addresses are, ~ because they're not randomized. ~ -~ This routine is really only responsible for one-time initialization. +~ Notably, though cold-start points rbp to the control stack, it leaves +~ the control stack empty, so trying to return will pop a value that doesn't +~ exist, and crash. Eventually, the bottom value on the control stack will +~ be the word "quit", which loops forever and is the closest thing Forth has +~ to a "main" word, but it's up to warm-start to make that happen. +~ +~ Cold-start is really only responsible for one-time initialization. +~ +~ ~ ~ Registers in: ~ @@ -186,11 +194,9 @@ ~ ~ Registers out: ~ -~ * rsi points within "quit" -~ Quit is the word that's Forth's closest equivalent to main(). +~ * rsi points within "warm-start" ~ * rsp points to the top of the value stack -~ -~ Notably, rbp is still uninitialialized after _start. +~ * rbp points to the top of the control stack ~ ~ Stack in: ~ diff --git a/log-load.e b/log-load.e index f386b26..e496e04 100644 --- a/log-load.e +++ b/log-load.e @@ -199,7 +199,15 @@ ~ ~ (log address, string pointer -- log address, execution token or 0) : log-load-find-execution-token - log-load-find dup { entry-to-execution-token } if ; + dup 3unroll log-load-find dup + { + 3roll drop + entry-to-execution-token + } { + drop swap + ." No such word: " emitstring newline + 0 + } if-else ; ~ This is the same as "create", from interpret.e, except that it takes the diff --git a/transform.e b/transform.e index 723484c..507c1f1 100644 --- a/transform.e +++ b/transform.e @@ -826,6 +826,53 @@ allocate-transform-state s" transform-state" variable ; make-immediate +~ It's convenient to be able to work with strings in label-transformed +~ code. If we don't provide an alternate for it, we get codeword pointers in +~ the host address space, which therefore don't work. +: label-string-alternate + ~ Wrapping s" is surprisingly difficult; see log-load-string-alternate + ~ for detailed notes on how it works. This is pretty much the same + ~ implementation, except the label transform doesn't track user stack depth + ~ so we don't have to worry about that part. + interpreter-flags @ + ' s" entry-to-execution-token + swap-transform-variables + ~ Since [ is an immediate word, we have to go to extra trouble to compile + ~ it as part of the alternate. + [ ' [ entry-to-execution-token , ] + execute + swap-transform-variables + swap interpreter-flags ! + ~ Whew. What a mouthful. + ~ (string pointer) + + ~ Now. If we are in immediate mode, we've left the string on the stack and + ~ that's all we wanted. If we're in compile mode, it's our job to output + ~ a litstring invocation. + interpreter-flags @ 0x01 & { + swap-transform-variables + L@' litstring + swap-transform-variables + + offset-to-target-address-space , ~ litstring + here @ swap packstring 8 packalign here ! + } if + ; make-immediate + + +: label-dot-string-alternate + ' label-string-alternate entry-to-execution-token execute + + interpreter-flags @ 0x01 & { + swap-transform-variables + L@' emitstring + swap-transform-variables + + offset-to-target-address-space , ~ emitstring + } { emitstring } if-else + ; make-immediate + + ~ Because docol requires it, we provide a special mini-version of the label ~ system. We only do L@' and L!', because that's all we need. These are real ~ labels; there can be arbitrarily many of them, and they can have forward @@ -1028,6 +1075,11 @@ allocate-transform-state s" transform-state" variable dup s" ;" stringcmp 0 = { swap drop ' label-semicolon-alternate swap } if dup s" ;asm" stringcmp 0 = { swap drop ' label-semicolon-assembly-alternate swap } if + ~ It is nontrivial to construct a string with a double-quote in it. + dup ' s" entry-to-name stringcmp 0 = { + swap drop ' label-string-alternate swap } if + dup ' ." entry-to-name stringcmp 0 = { + swap drop ' label-dot-string-alternate swap } if dup s" L@'" stringcmp 0 = { swap drop ' label-L@'-alternate swap } if dup s" L!'" stringcmp 0 = { swap drop ' label-L!'-alternate swap } if dup s" keyword" stringcmp 0 = { |