diff options
| -rw-r--r-- | transform.e | 59 |
1 files changed, 46 insertions, 13 deletions
diff --git a/transform.e b/transform.e index 30a9230..a75ea05 100644 --- a/transform.e +++ b/transform.e @@ -3469,27 +3469,60 @@ allocate-transformation-state s" transformation-state" variable : hex-self-codeword-alternate self-codeword ; : hex-string-alternate - ~ See label-string-alternate for detailed notes on how we wrap s". - ~ Essentially, we call the immediate version of it, in the outer context, - ~ which uses scratch space in the outer, "real" log. + ~ The technique we use to wrap s" is analogous to how we do it in the + ~ label transform, but with one critical decision different. + ~ + ~ In the label transform, the output buffer is going to be written + ~ directly into the final executable at some point, and we'd really rather + ~ not scribble temporary values into it, even if we expect to overwrite them + ~ later. Additionally, everything the label transform does runs inside the + ~ label loop, so the code it's transforming isn't expected to do any sort of + ~ miscellaneous setup things, just define a bunch of words. In that + ~ situation, making sure to use temporary space from the outer, "real" log + ~ is helpful. + ~ + ~ In the hex transform, most of that is different. The output buffer will + ~ include all sorts of things that don't become part of the final + ~ executable, though they're used in producing it. So, it's fine to use it + ~ for scratch space. Additionally, using the outer log for string literals + ~ gets us into trouble, since some of these temporary strings need to be + ~ made more durable by calling allocate-string on them. If we do that with + ~ a string pointer backed by the outer log, the inner "here" will wind up + ~ pointing to the end of the outer log, and all sorts of things will start + ~ scribbling atop each other. + ~ + ~ We do still benefit from using the interpreted version of s" rather than + ~ the compiled one; as with the label transform, it's convenient to handle + ~ the litstring dance ourselves. + ~ + ~ If we're in compile mode, we have reinvented a problem which the + ~ regular, non-transformed s" already deals with: The temporary space we're + ~ writing to is in the same place as the code we're compiling. We solve it + ~ the same way: Check beforehand and write out the call to litstring if we + ~ need it, so that we won't have to slide things around later. + interpreter-flags @ 0x01 & { + ~ We look up the inner version of litstring to reference here. This is + ~ similar to what the label transform does, except we don't use a label + ~ for it. + s" litstring" find entry-to-execution-token , + } if + + ~ Now, regardless of what mode we're actually in, call the interpreted + ~ version of s" to read the actual string and its null terminator. interpreter-flags @ ' s" entry-to-execution-token - swap-transform-variables [ ' [ entry-to-execution-token , ] execute - swap-transform-variables swap interpreter-flags ! ~ Now we have a string pointer on the stack at transform time. If we're in - ~ immediate mode, that's sufficient. If we're in compile mode, output a - ~ litstring invocation. Notice also that these are essentially the same - ~ responsibilities as we'd have in the label transform. + ~ immediate mode, that's sufficient. If we're in compile mode, we also + ~ already output a litstring invocation, and the string is in the right + ~ place, but "here" is pointing before it and needs to point after it, then + ~ we also still need to add alignment padding. Plus, we need to be sure to + ~ not leave the string pointer itself on the stack. interpreter-flags @ 0x01 & { - ~ We look up the inner version of litstring to reference here. This is - ~ similar to what the label transform does, except we don't use a label - ~ for it. - s" litstring" find entry-to-execution-token , - here @ swap packstring 8 packalign here ! + dup stringlen 1+ + 8 packalign here ! } if ; make-immediate |