about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--transform.e253
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