diff options
Diffstat (limited to 'transform.e')
| -rw-r--r-- | transform.e | 69 |
1 files changed, 61 insertions, 8 deletions
diff --git a/transform.e b/transform.e index 9637aee..6328e82 100644 --- a/transform.e +++ b/transform.e @@ -3244,16 +3244,19 @@ allocate-transformation-state s" transformation-state" variable ' ] entry-to-execution-token execute ; + ~ This word gets installed as a trap at the beginning of every Forth word, ~ so that it can examine the control stack and produce kinds of metadata that ~ require information that only exists at runtime. See ~ hex-semicolon-alterante, below, for details of how it's installed. ~ ~ It is worth noting that hex-trap can coexist with the more-targeted traps -~ installed by hex-colon-alternate. It runs before them, because +~ installed by hex-colon-alternate, above. It runs before them, because ~ hex-colon-alternate prepends its stuff first and then -~ hex-semicolon-alternate slides that all forward to prepend some more. +~ hex-semicolon-alternate slides that all forward to prepend the call to +~ hex-trace. : hex-trace + exit ~ value@ here @ swap 0 hex-output-metadata-entry-type-line-comment ~ add-hex-output-metadata-entry newline @@ -3267,14 +3270,59 @@ allocate-transformation-state s" transformation-state" variable ~ transform implementation", above, and make sure it's fresh in your mind. ~ ~ It's important to notice that, as we walk it, the values of "here" and - ~ "latest" reflect the log and dictionary of the code being transformed, not - ~ the log and dictionary of the outer program. Therefore, we can use - ~ containing-entry to find the entry headers. We can't use is-in-log, - ~ though, because the output buffer is - control@ { dup r0 @ > } - { dup @ symbolize-pointer newline 8 + } while + ~ "latest" reflect the log and dictionary of the code being transformed, ie. + ~ they are the ones in the output buffer, not the log and dictionary of the + ~ outer program. Therefore, we can use containing-entry to find the entry + ~ headers for words inside the transform, and if we want to look at words + ~ outside the transform we can wrap containing-entry in + ~ swap-transform-variables. We can't use is-in-log, though, because the + ~ label-loop buffer is inside the output buffer, which is inside the outer + ~ log, so it doesn't make the distinctions we need it to. + ~ + ~ Every word inside the transform will have hex-transform-one exactly once + ~ in its call chain, so we walk the control stack only up to that point. + control@ + { ~ First, check to make sure we haven't run off the bottom of the control + ~ stack. Remember, the control stack is an array of pointers, so this is a + ~ simple bounds check. + dup r0 @ > + + ~ If it is, we also want to look at what it points to. + dup { + ~ Dereference the pointer we've been iterating (... we're actually + ~ looking at a pointer to a pointer ...), and check that it's not inside + ~ hex-transform-one's body. + drop dup @ + + ~ The inner dictionary is inside the outer log, so we'll get an entry + ~ header regardless of which dictionary we consider, but it may not be + ~ the one we care about. If we want to get the correct entry pointer, we + ~ have to make sure we're looking at the outer dictionary. + swap-transform-variables + + ~ Check what entry the control pointer is in. + containing-entry + + ~ Get the entry for hex-transform-one to compare against. This would + ~ be a forward reference, so we need to look it up at runtime. + s" hex-transform-one" find + + ~ Now switch back. + swap-transform-variables + + ~ If they're equal, we want to stop the loop. + != + } if } + { dup @ + + symbolize-pointer space + + ~ Iterate to the next pointer in the control stack. It's an array of + ~ pointers, so this is just arithmetic. + 8 + } while drop ; + ~ We want to trace every call to a Forth word, for use in generating ~ metadata. To do this, we want to add a prefix trap to the calls, but we ~ can't put the logic in hex-colon-alternate because we don't know which @@ -3333,6 +3381,7 @@ allocate-transformation-state s" transformation-state" variable [ ' ; entry-to-execution-token , ] ; make-immediate + : hex-semicolon-assembly-alternate latest @ entry-to-name dup s" sys-write" stringcmp 0 = { @@ -3354,6 +3403,7 @@ allocate-transformation-state s" transformation-state" variable [ ' ;asm entry-to-execution-token , ] ; 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. Unlike with the ~ label transform, these are NOT real labels; they're restricted similarly to @@ -3384,6 +3434,7 @@ allocate-transformation-state s" transformation-state" variable transformation-state transformation-state-label-scratch ! ; make-immediate + ~ We have to provide alternates for the globals that are bootstrapped by ~ warm-start in normal execution, because code under the hex transform never ~ gets its own copy of warm-start. They don't have to do anything special, @@ -3397,6 +3448,7 @@ allocate-transformation-state s" transformation-state" variable : hex-latest-alternate latest ; : hex-here-alternate here ; + ~ The code we're compiling may try to exit when it's done. We want to return ~ to our caller instead; we turn that into an nop. This isn't quite correct, ~ but it will work as long as the inner code doesn't try to do anything else @@ -3458,6 +3510,7 @@ allocate-transformation-state s" transformation-state" variable dup { entry-to-execution-token execute } { drop allocate } if-else } if-else ; make-immediate + ~ This implements the hex transform for a single word. It is directly ~ analogous to "interpret", and reading interpret.e may help in understanding ~ it, though it's meant to still make sense on its own. |