diff options
| author | Irene Knapp <ireneista@irenes.space> | 2026-09-10 06:41:22 -0700 |
|---|---|---|
| committer | Irene Knapp <ireneista@irenes.space> | 2026-09-10 06:41:22 -0700 |
| commit | 7a0a28f4d8b738d305b826b5464b27255dd7def3 (patch) | |
| tree | 0b14a86147b526842445f0e447ab8be35e13525b /transform.e | |
| parent | a46d5888321d859ed5c6698292fda45fd2633497 (diff) | |
add some magic comment commands to reorder subitems more generally
these are all fully working and debugged. they have been used in a principled attempt to get all the parameter orders in amd64.e correct, but that effort needs to be verified carefully, which it hasn't been, yet. a couple of missing magic comments in elf.e and execution.e were also added. Force-Push: yes Change-Id: Id4c48b121a71b4f945ee3718e14a06f07afd7304
Diffstat (limited to 'transform.e')
| -rw-r--r-- | transform.e | 117 |
1 files changed, 112 insertions, 5 deletions
diff --git a/transform.e b/transform.e index 9a2cb21..5bec117 100644 --- a/transform.e +++ b/transform.e @@ -2786,6 +2786,8 @@ allocate-transformation-state s" transformation-state" variable ~ ~ : provide-hex64 ~ ~ : provide-keyword ~ ~ : drop-subitem +~ ~ : swap-subitems +~ ~ : 3 roll-subitems ~ ~ By the way, the reason it's possible to write these examples is that ~ they're all embedded within an outer comment, the text you're reading, so @@ -3139,7 +3141,10 @@ allocate-transformation-state s" transformation-state" variable ~ With all this context, it likely doesn't need much explanation, but the ~ drop-subitem command will create an -entry-type-drop-substring entry. When ~ this entry is executed, it will discard an item from the substring entry -~ stack. +~ stack. Similarly, swap-subitems creates an -entry-type-swap-substrings, +~ which swaps the top two items, and roll-subitems creates an +~ -entry-type-roll-substrings, which rolls them, or unrolls them with a +~ negative parameter. ~ ~ One more thing: The order in which provide-* commands execute will most ~ likely match the order in which the corresponding bytes are output. This may @@ -3205,6 +3210,8 @@ allocate-transformation-state s" transformation-state" variable : hex-output-metadata-entry-type-push-substring-hex64 12 ; : hex-output-metadata-entry-type-push-substring-string 13 ; : hex-output-metadata-entry-type-drop-substring 14 ; +: hex-output-metadata-entry-type-swap-substrings 15 ; +: hex-output-metadata-entry-type-roll-substrings 16 ; ~ Initialize the contents of the output metadata to all zeroes. This is ~ called from hex-transform at its top level, at the very start, to make sure @@ -3252,7 +3259,8 @@ allocate-transformation-state s" transformation-state" variable || ; : is-push-substring-entry - ~ Notably, -entry-type-drop-substring is not a push-substring entry. + ~ Notably, the substring swap, drop, and roll entry types are not + ~ push-substring entries. hex-output-metadata-entry-type @ dup hex-output-metadata-entry-type-push-substring-decimal = swap dup hex-output-metadata-entry-type-push-substring-hex8 = 3roll || swap @@ -3994,6 +4002,94 @@ allocate-transformation-state s" transformation-state" variable hex-output-metadata-entry-type-drop-substring = { pop-substring-entry-stack drop } if + + dup hex-output-metadata-entry-type @ + hex-output-metadata-entry-type-swap-substrings = { + ~ Just like in hex-emit-template-string, we want to make sure to + ~ discard the zeroes we get if we underflow the stack. + pop-substring-entry-stack + pop-substring-entry-stack + swap + dup { push-substring-entry-stack } { drop } if-else + dup { push-substring-entry-stack } { drop } if-else + } if + + dup hex-output-metadata-entry-type @ + hex-output-metadata-entry-type-roll-substrings = { + ~ The parameter giving the amount to roll by is in the string field. + dup hex-output-metadata-entry-string @ + ~ (... amount to roll by) + + ~ We resist the temptation to do the memcopy math. We don't need + ~ to, since the regular Forth roll and unroll do it for us. + dup 0 < { + ~ In this scenario, we're rolling. The amount to roll by is also + ~ the number of items. + + 0 { 2dup < } { pop-substring-entry-stack 3unroll 1+ } while + drop + ~ (... items, amount to roll by / number of items) + + ~ Please notice that the items we have popped from the substring + ~ entry stack are now, on the value stack, in the reverse of the + ~ order they were on the entry stack. They will reverse again when + ~ we push them back. + ~ + ~ The amount to roll by is positive, so the desired operation is + ~ a regular roll. Since the entries are reversed right now, we + ~ unroll them, which will be what we want when we put them back. + ~ + ~ Try it out interactively with a toy example and convince + ~ yourself. It's hard to really model in your head, but it's true. + ~ The intuition is that, if you're looking at the value stack, + ~ the bottommost item there will be the topmost one after + ~ re-reversing, so we think of our operations as proceeding + ~ up-stack from there, instead of the usual operations that start + ~ at the topmost item and proceed downwards. + ~ + ~ Anyway, this little trick does a regular unroll, which acts as + ~ a roll, and keeps the value around. + dup 3unroll 1+ unroll + } if + ~ (... items if positive, amount to roll by) + + ~ We did the positive case first, which means the amount to roll + ~ by is still its original value, regardless of whether that case + ~ ran or not. So, we can check if it's negative to see if we need + ~ to do the negative case. + dup 0 > { + ~ In this scenario, we're unrolling. We negate the amount to + ~ roll by to get the amount to unroll by, which is also the number + ~ of items. + negate + + 0 { 2dup < } { pop-substring-entry-stack 3unroll 1+ } while + drop + ~ (... items, number of items) + + ~ The parameter was negative, so we were asked to do an unroll. + ~ This trick does a roll, and keeps the value. Notice that "roll" + ~ always needs a positive amount. + dup 1+ roll swap + } if + ~ (... items, number of items) + + ~ Now, regardless of which case ran, we have the items and we have + ~ a non-negative count of them. Notice that if we were asked to roll + ~ by zero, neither case ran, but that still describes what we have + ~ accurately. + + ~ Now we push them back. + 0 { 2dup < } { + 3roll + + ~ Again, if we underflowed we got zeros, and we discard them. + dup { push-substring-entry-stack } { drop } if-else + + 1+ + } while + drop drop + } if } if hex-output-metadata-next-entry } while @@ -4877,9 +4973,20 @@ allocate-transformation-state s" transformation-state" variable } if dup s" drop-subitem" stringcmp 0 = { ~ Create a new "drop substring" entry. - drop drop - 2 pick execution-token-to-entry entry-to-name - hex-output-metadata-entry-type-drop-substring swap + drop drop hex-output-metadata-entry-type-drop-substring 0 + add-hex-output-metadata-entry + exit + } if + dup s" swap-subitems" stringcmp 0 = { + ~ Create a new "swap substrings" entry. + drop drop hex-output-metadata-entry-type-swap-substrings 0 + add-hex-output-metadata-entry + exit + } if + dup s" roll-subitems" stringcmp 0 = { + ~ Create a new "roll substrings" entry. The parameter goes in the string + ~ field, and the length is always zero. + drop drop 0 swap hex-output-metadata-entry-type-roll-substrings swap add-hex-output-metadata-entry exit } if |