diff options
Diffstat (limited to 'transform.e')
| -rw-r--r-- | transform.e | 68 |
1 files changed, 67 insertions, 1 deletions
diff --git a/transform.e b/transform.e index 9605341..3079414 100644 --- a/transform.e +++ b/transform.e @@ -2606,6 +2606,12 @@ allocate-transformation-state s" transformation-state" variable ~ The hex transform DOES NOT WORK yet. It's still in development. ~ TODO update this note when it does work +~ The hex transform keeps some large, complex state as it runs, unlike the +~ label and log-load transforms, which only require very simple state. This +~ state is called the "output metadata"; a buffer for storing it is provided +~ by the transform's caller, and referenced during the transform via +~ transformation-state-output-metadata. +~ ~ The output metadata is a header structure followed by an array of ~ entry structures, as follows: ~ @@ -3145,7 +3151,67 @@ allocate-transformation-state s" transformation-state" variable ' ] entry-to-execution-token execute ; -: hex-semicolon-alternate [ ' ; entry-to-execution-token , ] +: hex-trace + ~ value@ here @ swap 0 hex-output-metadata-entry-type-line-comment + ~ add-hex-output-metadata-entry + ." tracey tracey" newline ; + +~ 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 +~ words are Forth words and which are assembly words until we see the +~ semicolon. +~ +~ So, we do it here in hex-semicolon-alternate. The word body has already +~ been compiled at this point, so we slide the whole body forward to make +~ room. This is explicitly allowed by our compilation model; you may be +~ aware that it's also how high-level flow control is implemented. +~ +~ You might find it useful to compare this code to the implementations of +~ high-level flow-control utilities in log-load.e; it operates under a very +~ similar set of constraints, except that fortunately we don't have the +~ nightmare multi-dictionary situation that the log-load transform does. +: hex-semicolon-alternate + latest @ entry-to-execution-token 8 + + dup dup dup + ~ (start, start, start, start) + + ~ The actual body of the trap is just a single word long (see below). If + ~ that ever changes, make sure to keep the amount we slide by in sync with + ~ it. + 8 + swap ~ TODO change number of words + ~ (start, start, adjusted start, start) + + here @ swap - + ~ (start, start, adjusted start, length) + + memmove + ~ (start) + + ~ We're going to use comma to append compiled code, so let's swap out the + ~ value of "here" to point to the space we just opened up. + here @ swap here ! + ~ (old "here") + + ~ This applies to every single word terminated with semicolon, which is + ~ all the Forth words that are created directly rather than with "variable" + ~ or some similar high-level facility. Because we also can't have forward + ~ references, that means we can't assume we'll have any available words in + ~ the transformed code to call, at all. So, the only thing we can usefully + ~ have the trap do is call a word that's defined as part of the transform. + ~ + ~ Fortunately, we do get to assume there will be a normal entry header in + ~ place for the word we're trapping. So we don't need to scrounge up any + ~ runtime data for the trap's benefit; the trap will be able to get what it + ~ needs by inspecting the control stack and the log. + ' hex-trace entry-to-execution-token , + + ~ We're done compiling the trap's contents, so swap "here" back. Again, + ~ keep this in sync with the length of the trap. + 8 + here ! + + ~ Now we do the regular semicolon stuff. + [ ' ; entry-to-execution-token , ] ; make-immediate : hex-semicolon-assembly-alternate |