diff options
| author | Irene Knapp <ireneista@irenes.space> | 2026-05-21 00:23:32 -0700 |
|---|---|---|
| committer | Irene Knapp <ireneista@irenes.space> | 2026-05-21 00:23:32 -0700 |
| commit | 189f0c0de22150f944e067b686b4cfe81af5fcb8 (patch) | |
| tree | e77213734e4260b3e9a33016d85ddcb233bd7912 | |
| parent | d784695204db078a8f1731f93d12117f6e53c317 (diff) | |
okay, s" and ." work all-the-way in the log-load transform now
wow those were hard ones. it's very squirelly what happens when. hopefully these new and reorganized docs will make it easier to understand next time... Force-Push: yes Change-Id: I8f3b86900ca1794afc3e607c2180dd05ea168cc7
| -rw-r--r-- | log-load.e | 18 | ||||
| -rw-r--r-- | transform.e | 130 |
2 files changed, 122 insertions, 26 deletions
diff --git a/log-load.e b/log-load.e index e496e04..4649403 100644 --- a/log-load.e +++ b/log-load.e @@ -355,3 +355,21 @@ ~ (log address, output point, here) ! ; + +~ This is a helper used by log-load-string-alternate. It does the usual +~ string packing thing, but at one layer of indirection more than usual. Its +~ responsibility includes alignment, unlike packstring. +~ +~ (log address, string pointer -- log address) +: log-load-comma-string + swap log-load-here @ 3roll + ~ (log address, output point, string pointer) + + packstring + 8 packalign + ~ (log address, output point) + + swap log-load-here 3roll swap + ~ (log address, output point, here) + ! ; + diff --git a/transform.e b/transform.e index 236c031..a137c0c 100644 --- a/transform.e +++ b/transform.e @@ -829,10 +829,21 @@ allocate-transform-state s" transform-state" variable ~ 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. + ~ Something subtle here: s" is state-dependent. That is, it does different + ~ things depending on the interpreter flags. We would really rather know + ~ which version we're getting, and also it would be best if it didn't + ~ scribble on the output buffer. Fortunately we can achieve both of these, + ~ by coercing things into a known state while calling it. + ~ + ~ We could choose either version of s", but the interpreted one is more + ~ convenient because it doesn't mess with a spurious litstring invocation, + ~ just scribbled into scratch space after "here". Of course, that raises the + ~ additional concern that we have the wrong "here", but we can just swap + ~ that around, too. + ~ + ~ This is all worth it to avoid reimplementing s". If we had two + ~ implementations, they'd have to be kept in sync, and it's an important + ~ user-facing word with semantics that are likely to improve over time. interpreter-flags @ ' s" entry-to-execution-token swap-transform-variables @@ -842,12 +853,15 @@ allocate-transform-state s" transform-state" variable execute swap-transform-variables swap interpreter-flags ! + ~ Whew. What a mouthful. - ~ (string pointer) + ~ + ~ Having done this, we have the string pointer on the stack at transform + ~ time, which with the label transform is the same as immediate time. If + ~ we're in immediate mode, therefore, 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. - ~ 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 @@ -1726,21 +1740,10 @@ allocate-transform-state s" transform-state" variable ~ Strings are important and must happen now, now, now. : log-load-string-alternate - ~ Something subtle here: s" is state-dependent. That is, it does different - ~ things depending on the interpreter flags. We would really rather know - ~ which version we're getting, and also it would be best if it didn't - ~ scribble on the output buffer. Fortunately we can achieve both of these, - ~ by coercing things into a known state while calling it. - ~ - ~ We could choose either version of s", but the interpreted one is more - ~ convenient because it doesn't mess with a spurious litstring invocation, - ~ just scribbled into scratch space after "here". Of course, that raises the - ~ additional concern that we have the wrong "here", but we can just swap - ~ that around, too. - ~ - ~ This is all worth it to avoid reimplementing s". If we had two - ~ implementations, they'd have to be kept in sync, and it's an important - ~ user-facing word with semantics that are likely to improve over time. + ~ Wrapping s" is surprisingly difficult; see label-string-alternate + ~ for detailed notes on how that works. Once we've finished the + ~ transform-time part, our implementations will diverge, but this first bit + ~ is the same. interpreter-flags @ ' s" entry-to-execution-token swap-transform-variables @@ -1750,8 +1753,24 @@ allocate-transform-state s" transform-state" variable execute swap-transform-variables swap interpreter-flags ! - ~ Whew. What a mouthful. - ~ (string pointer) + + ~ Nope, doing it twice didn't make that any less of a mouthful. + ~ + ~ Having done this, we have the string pointer on the stack at transform + ~ time (not, mind you, at log-load time, as yet). Now it is our job to + ~ either compile it, or invoke it "immediately". Recall that the log-load + ~ transform's "immediate" time, which we also call log-load time, is + ~ analogous to the label transform's "compile" time. The log-load + ~ transform's "compile" time is an additional layer of indirection. + ~ + ~ No matter which mode we're in, the first thing we want to do is get the + ~ string onto the value stack at log-load time. So we compile code to do + ~ that, first. We do that using the static "litstring", which we find by + ~ label. + ~ + ~ If this is all too twisty, it might be helpful to go re-read the + ~ definition of log-load-compile-literal, which does a simpler version of + ~ this same task (because integers are easier than strings). swap-transform-variables L@' litstring @@ -1760,8 +1779,65 @@ allocate-transform-state s" transform-state" variable offset-to-target-address-space , ~ litstring here @ swap packstring 8 packalign here ! - ~ Now the string pointer is on the stack, so we apply a delta for it. + ~ Now the string pointer is on the stack at log-load time, so we apply a + ~ delta for it. 1 transform-apply-stack-delta + + ~ If we're in immediate mode, we're done! Yay! Putting the string on the + ~ stack at log-load time is what we wanted. If not... + interpreter-flags @ 0x01 & { + ~ We're in compile mode, so we need to look up the ultimate, dynamic, + ~ log-based, super-atomic space rocket copy of "litstring" and use that. + ~ We could call log-load-compile-dynamic-word here, but, as usual, it + ~ would produce some excessive rolling and unrolling, so we do its job + ~ ourselves instead. + log-load-roll-log-address + + swap-transform-variables + ~ As usual, we do these in reverse. + L@' log-load-comma-string + L@' swap + L@' log-load-comma + L@' log-load-find-execution-token + L@' litstring + swap-transform-variables + + ~ The overall stack delta of this sequence is 0. + offset-to-target-address-space , ~ litstring + here @ s" litstring" packstring 8 packalign here ! + offset-to-target-address-space , ~ log-load-find-execution-token + offset-to-target-address-space , ~ log-load-comma + offset-to-target-address-space , ~ swap + offset-to-target-address-space , ~ log-load-comma-string + + ~ We consumed the string pointer at log-load time, so we apply a delta + ~ for it. + ~ + ~ Notice by the way how the nearby calls to log-load-unroll-log-address + ~ rely on this being split into two deltas like this, even though they + ~ net out to zero; we aren't doing it just for kicks. + -1 transform-apply-stack-delta + + log-load-unroll-log-address ; + } if + ; make-immediate + + +: log-load-dot-string-alternate + ' log-load-string-alternate entry-to-execution-token execute + + interpreter-flags @ 0x01 & { + ~ Hey look, it's the one time we're doing something simple enough that + ~ we can actually benefit from log-load-compile-dynamic-word as something + ~ more than an example to start from. :) + s" emitstring" log-load-compile-dynamic-word + } { + swap-transform-variables + L@' emitstring + swap-transform-variables + + offset-to-target-address-space , ~ emitstring + } if-else ; make-immediate @@ -1865,6 +1941,8 @@ allocate-transform-state s" transform-state" variable ~ It is nontrivial to construct a string with a double-quote in it. dup ' s" entry-to-name stringcmp 0 = { swap drop ' log-load-string-alternate swap } if + dup ' ." entry-to-name stringcmp 0 = { + swap drop ' log-load-dot-string-alternate swap } if dup s" L@'" stringcmp 0 = { swap drop ' log-load-L@'-alternate swap } if dup s" L!'" stringcmp 0 = { swap drop ' log-load-L!'-alternate swap } if ~ (name as stack string, 0 or alternate entry pointer, name pointer) |