diff options
Diffstat (limited to 'transform.e')
| -rw-r--r-- | transform.e | 253 |
1 files changed, 234 insertions, 19 deletions
diff --git a/transform.e b/transform.e index 13dce31..e9b7e0c 100644 --- a/transform.e +++ b/transform.e @@ -907,7 +907,9 @@ allocate-transformation-state s" transformation-state" variable ~ : provide-string-copy ~ : # is defined here via the label transform; this is its entry header. ~ : indent - dup stringlen 1 + dup 3unroll + dup stringlen 1 + + ~ : provide-data + dup 3unroll here @ 10 + swap memmove here @ @@ -917,8 +919,12 @@ allocate-transformation-state s" transformation-state" variable ~ conversion is host-address-space-to-target. ~ : 8 (previous entry pointer) latest @ host-address-space-to-target pack64 - 0 pack8 ~ : -1 (entry flags) - 0 pack8 ~ : -1 (null reverse-terminator) + ~ : 1 (entry flags) + 0 pack8 + ~ : double-null-terminated entry name + 0 pack8 + ~ : 1 data-adjust-output-point + ~ : fresh-line + 8 packalign here @ latest ! @@ -2837,6 +2843,10 @@ allocate-transformation-state s" transformation-state" variable ~ ~ : blank-line ~ ~ ~ : 1 adjust-length +~ ~ : -10 adjust-start +~ ~ : 1 data-adjust-length +~ ~ : -1 data-adjust-start +~ ~ : 1 data-adjust-output-point ~ ~ : 1 suppress ~ ~ ~ : Do a thing with # and # ? @@ -2850,6 +2860,7 @@ allocate-transformation-state s" transformation-state" variable ~ ~ : provide-string ~ ~ : provide-string-copy ~ ~ : provide-keyword +~ ~ : provide-data ~ ~ : drop-subitem ~ ~ : swap-subitems ~ ~ : 3 roll-subitems @@ -3012,6 +3023,28 @@ allocate-transformation-state s" transformation-state" variable ~ Feel free to consult the convention described at the top of amd64.e for ~ inspiration. ~ +~ All the adjust-* commands change something immediately, as they execute. +~ What they adjust differs. In the cases of adjust-length and adjust-start, +~ it's a field of a recent entry. Notionally, adjust-start does the same thing +~ as adjust-length but for the start address the entry is attached to, rather +~ than the length of the attachment. Also, while adjust-length only affects +~ comment entries, adjust-start affects any entry that produces output, such +~ as fresh-line. Meanwhile, adjust-output-point directly modifies the latest +~ output point, which can be useful if a location has been skipped over +~ without outputting anything. +~ +~ The data-adjust-* variants deserve further commentary, though you may find +~ it more productive to read and understand the entire explanation about +~ provide-* commands before worrying about these. These variants adjust the +~ same things as the non-data ones, but instead of adjusting by a fixed +~ amount, they look for the most recent -entry-type-saved-data metadata entry. +~ They delete that entry from the entry array entirely, and use the value +~ saved in it as the amount to adjust by. Such entries are created by the +~ provide-data command, on which more below. Additionally, the data-adjust-* +~ commands use their parameters as scaling factors to the adjustment, and +~ these factors may be negative. You'll usually specify a parameter of 1 or +~ -1. +~ ~ We will revisit the topic of adjust-length later, when we describe the ~ comment template feature, but for now we'll leave it there. ~ @@ -3196,6 +3229,12 @@ allocate-transformation-state s" transformation-state" variable ~ keyword from the dictionary entry header. All three of these save pointer to ~ their respective strings in a push-subitem-string metadata entry. ~ +~ The -data variant treats the value as opaque, and creates an +~ -entry-type-saved-data metadata entry. Unlike the others, these entries do +~ not affect the subitem entry stack; they're consumed and removed from the +~ entry array before entry execution even starts, by the matching data-* +~ command. +~ ~ Admit it, you thought writing out "metadata entry" so many times instead ~ of just "entry" was silly because there was no other kind of entry in ~ consideration, right up until you got to "dictionary entry". If so, hey @@ -3245,6 +3284,10 @@ allocate-transformation-state s" transformation-state" variable ~ have come before or after the provide-* commands that go with the same ~ suffix comment. ~ +~ Now that you have this full picture in your head, you finally also have +~ the background to understand the data-adjust-* commands. You may find it +~ helpful to go re-read the explanation of them, above, to let it sink in. +~ ~ This is the kind of forwards-and-backwards thinking which humans are ~ surprisingly good at when reading and writing software, but which it's ~ quite difficult to formalize in a way that lets a computer share that @@ -3290,9 +3333,10 @@ allocate-transformation-state s" transformation-state" variable : hex-output-metadata-entry-type-push-subitem-hex32 11 ; : hex-output-metadata-entry-type-push-subitem-hex64 12 ; : hex-output-metadata-entry-type-push-subitem-string 13 ; -: hex-output-metadata-entry-type-drop-subitem 14 ; -: hex-output-metadata-entry-type-swap-subitems 15 ; -: hex-output-metadata-entry-type-roll-subitems 16 ; +: hex-output-metadata-entry-type-saved-data 14 ; +: hex-output-metadata-entry-type-drop-subitem 15 ; +: hex-output-metadata-entry-type-swap-subitems 16 ; +: hex-output-metadata-entry-type-roll-subitems 17 ; ~ 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 @@ -3335,9 +3379,18 @@ allocate-transformation-state s" transformation-state" variable : is-comment-entry hex-output-metadata-entry-type @ - dup hex-output-metadata-entry-type-line-comment = - swap hex-output-metadata-entry-type-suffix-comment = - || ; + dup hex-output-metadata-entry-type-line-comment = swap + hex-output-metadata-entry-type-suffix-comment = || ; + +: is-output-producing-entry + dup is-comment-entry swap + hex-output-metadata-entry-type @ + dup hex-output-metadata-entry-type-fresh-line = 3roll || swap + hex-output-metadata-entry-type-blank-line = || ; + +: is-saved-data-entry + hex-output-metadata-entry-type @ + hex-output-metadata-entry-type-saved-data = ; : is-push-subitem-entry ~ Notably, the subitem swap, drop, and roll entry types are not @@ -3420,7 +3473,7 @@ allocate-transformation-state s" transformation-state" variable ~ We still consume the value, so that our caller doesn't crash. drop - ." Substring entry stack overflow." newline + ." Subitem entry stack overflow." newline } if-else ; : pop-subitem-entry-stack @@ -3431,7 +3484,7 @@ allocate-transformation-state s" transformation-state" variable hex-output-metadata-subitem-entry-stack-zero subitem-entry-stack-depth@ 8 * + @ } { - ." Substring entry stack underflow." newline + ." Subitem entry stack underflow." newline ~ We still return a value, so that our caller doesn't crash. 0 @@ -3474,16 +3527,20 @@ allocate-transformation-state s" transformation-state" variable 0 pack64 drop } { drop drop drop drop } if-else ; -~ (length adjustment --) -: adjust-latest-hex-output-metadata-entry-length - ~ First, loop forward from the beginning of the entry array to find the - ~ last actual entry. +~ (-- entry pointer or 0) +: find-latest-metadata-entry + ~ Loop forward from the beginning of the entry array to find the last + ~ actual entry. transformation-state transformation-state-output-metadata @ hex-output-metadata-first-entry dup @ { { dup hex-output-metadata-next-entry @ } { hex-output-metadata-next-entry } while - } if + } if ; + +~ (-- entry pointer or 0) +: find-latest-comment-metadata-entry + find-latest-metadata-entry ~ (entry pointer or 0) ~ If and only if we actually found one, now loop backwards to find the @@ -3495,6 +3552,42 @@ allocate-transformation-state s" transformation-state" variable over > { hex-output-metadata-previous-entry } { drop 0 } if-else } while ~ (entry pointer or 0) + ; + +~ (-- entry pointer or 0) +: find-latest-output-producing-metadata-entry + find-latest-metadata-entry + ~ (entry pointer or 0) + + ~ If and only if we actually found one, now loop backwards to find the + ~ most recent one that's an output-producing entry. + { dup { dup is-output-producing-entry not } { 0 } if-else } + { transformation-state transformation-state-output-metadata @ + hex-output-metadata-first-entry + over > { + hex-output-metadata-previous-entry } { drop 0 } if-else } while + ~ (entry pointer or 0) + ; + +~ (-- entry pointer or 0) +: find-latest-saved-data-metadata-entry + find-latest-metadata-entry + ~ (entry pointer or 0) + + ~ If and only if we actually found one, now loop backwards to find the + ~ most recent one that's a comment entry. All length adjustments apply to + ~ comment entries, anything else needs to be skipped for this purpose. + { dup { dup is-saved-data-entry not } { 0 } if-else } + { transformation-state transformation-state-output-metadata @ + hex-output-metadata-first-entry + over > { + hex-output-metadata-previous-entry } { drop 0 } if-else } while + ~ (entry pointer or 0) + ; + +~ (length adjustment --) +: adjust-latest-comment-metadata-entry-length + find-latest-comment-metadata-entry ~ We've found the entry we want to act on, if it exists, so do it. dup { @@ -3508,6 +3601,78 @@ allocate-transformation-state s" transformation-state" variable crash } if-else ; +~ (length adjustment --) +: adjust-latest-output-producing-metadata-entry-start + find-latest-output-producing-metadata-entry + + ~ We've found the entry we want to act on, if it exists, so do it. + dup { + hex-output-metadata-entry-data-start dup @ 3roll + swap ! + } { + drop + + ~ If we get here, that's a problem. Emit an error message to make sure + ~ it's easy to diagnose. + ." No pre-existing metadata entry to adjust." newline + crash + } if-else ; + +~ (adjustment --) +: adjust-latest-output-point + transformation-state transformation-state-output-metadata @ + hex-output-metadata-latest-output-point + dup 3unroll @ + swap ! ; + +~ (entry pointer --) +: delete-metadata-entry + transformation-state transformation-state-output-metadata @ + hex-output-metadata-first-entry + { dup @ } { hex-output-metadata-next-entry } while + ~ (entry pointer, array-end marker pointer) + over hex-output-metadata-next-entry - 8 + + ~ (entry pointer, length of block to move) + swap dup hex-output-metadata-next-entry swap 3roll memmove ; + +~ (-- data value) +: data-consume + find-latest-saved-data-metadata-entry + ~ (entry pointer or 0) + + dup { + dup hex-output-metadata-entry-content @ swap + ~ (data value, entry pointer) + + delete-metadata-entry + } { + drop + + ~ If we get here, that's a problem. Emit an error message to make sure + ~ it's easy to diagnose. + ." No saved-data metadata entry to take a value from." newline + + ~ We still return a value, so that our caller doesn't crash. + 0 + } if-else ; + +~ (adjustment scale factor --) +: data-adjust-latest-comment-metadata-entry-length + data-consume + ~ (adjustment scale factor, data value) + + ~ All the entry array manipulation happened in data-consume. We're done + ~ doing that, and the array is now in a consistent state, so we can hand + ~ off to the non-data implementation to do the rest of the work. + * adjust-latest-comment-metadata-entry-length ; + +: data-adjust-latest-output-producing-metadata-entry-start + ~ Same as for adjusting the entry length. + data-consume * adjust-latest-output-producing-metadata-entry-start ; + +~ (adjustment scale factor --) +: data-adjust-latest-output-point + data-consume * adjust-latest-output-point ; + + ~ (count adjustment --) : adjust-hex-output-suppression-count transformation-state transformation-state-output-metadata @ @@ -4138,6 +4303,13 @@ allocate-transformation-state s" transformation-state" variable } if dup hex-output-metadata-entry-type @ + hex-output-metadata-entry-type-saved-data = { + ~ It's not valid to execute these, so print a diagnostic. They're + ~ supposed to always be consumed by data-* commands. + ." A saved-data metadata entry leaked." newline + } if + + dup hex-output-metadata-entry-type @ hex-output-metadata-entry-type-drop-subitem = { pop-subitem-entry-stack drop } if @@ -5074,8 +5246,38 @@ allocate-transformation-state s" transformation-state" variable ~ Now look for instruction keywords. These keywords are expected to be the ~ entire line, except that a length field can come before them. dup s" adjust-length" stringcmp 0 = { - ~ Modify the most recent entry by adjusting its length. - drop drop swap drop adjust-latest-hex-output-metadata-entry-length + ~ Modify the most recent comment entry by adjusting its length. + drop drop swap drop adjust-latest-comment-metadata-entry-length + exit + } if + dup s" adjust-start" stringcmp 0 = { + ~ Modify the most recent output-producing entry by adjusting its start. + drop drop swap drop adjust-latest-output-producing-metadata-entry-start + exit + } if + dup s" adjust-output-point" stringcmp 0 = { + ~ Modify the latest output point. + drop drop swap drop adjust-latest-output-point + exit + } if + + dup s" data-adjust-length" stringcmp 0 = { + ~ Modify the most recent comment entry by adjusting its length, also + ~ using data from the most recent data entry. + drop drop swap drop data-adjust-latest-comment-metadata-entry-length + exit + } if + dup s" data-adjust-start" stringcmp 0 = { + ~ Modify the most recent output-producing entry by adjusting its start, + ~ also using data from the most recent data entry. + drop drop swap drop + data-adjust-latest-output-producing-metadata-entry-start + exit + } if + dup s" data-adjust-output-point" stringcmp 0 = { + ~ Modify the latest output point, also using data from the most recent + ~ data entry. + drop drop swap drop data-adjust-latest-output-point exit } if @@ -5184,6 +5386,19 @@ allocate-transformation-state s" transformation-state" variable add-hex-output-metadata-entry exit } if + dup s" provide-data" stringcmp 0 = { + ~ Create a new "push subitem data" entry. + drop drop + 2 pick hex-output-metadata-entry-type-saved-data swap + add-hex-output-metadata-entry + exit + } if + + ~ Next are the subitem stack manipulation commands. These deal with the + ~ subitem entry stack, just as the provide-* commands do, but at this phase + ~ of processing the effect is just to create an entry in the entry array, + ~ not to do any actual stack manipulation, so their implementations are + ~ quite simple. dup s" drop-subitem" stringcmp 0 = { ~ Create a new "drop subitem" entry. drop drop hex-output-metadata-entry-type-drop-subitem 0 @@ -5197,7 +5412,7 @@ allocate-transformation-state s" transformation-state" variable exit } if dup s" roll-subitems" stringcmp 0 = { - ~ Create a new "roll subitem" entry. The parameter goes in the string + ~ Create a new "roll subitem" entry. The parameter goes in the content ~ field, and the length is always zero. drop drop 0 swap hex-output-metadata-entry-type-roll-subitems swap add-hex-output-metadata-entry |