about summary refs log tree commit diff
path: root/output.e
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@irenes.space>2026-09-28 16:48:30 -0700
committerIrene Knapp <ireneista@irenes.space>2026-09-28 17:07:09 -0700
commit54b8077d3296ae994c2943d0d39e84a4d4047416 (patch)
tree775a67d860930ef2f8f3b43b7c79fd10dde4ac18 /output.e
parent244072db39c1f6fa743fec38463f550f1b9608c4 (diff)
implement various pack-* words for turning numbers into strings
these are closely analogous to . and its variants, but follow the "pack" idiom so that they can be used in construction strings, instead of writing to standard output.

this was a longstanding TODO that is also needed in refactoring the high-level way compilation is initiated.

Force-Push: yes
Change-Id: Id315339da86a1f8aa4490a7475701a797a6cb56d
Diffstat (limited to 'output.e')
-rw-r--r--output.e64
1 files changed, 62 insertions, 2 deletions
diff --git a/output.e b/output.e
index b5414d4..45a29b7 100644
--- a/output.e
+++ b/output.e
@@ -103,8 +103,6 @@
 ~ recursion, and lets us stick entirely with the trivial control-flow
 ~ constructs we already have.
 ~
-~ TODO add a variant that writes to a string
-~
 ~ (integer to print, base to print in, width to zero-pad to --)
 : .base-unsigned
   ~ (input, base, width)
@@ -190,3 +188,65 @@
 ~ (integer to print, width --)
 : .hexn 16 swap .base-unsigned ;
 
+
+
+~   The control structure here is the same as .base-unsigned, but it outputs
+~ to a string.
+~
+~   The use of the "pack" nomenclature here is a little odd in that most other
+~ uses are for binary structures rather than text, but compare packstring.
+~
+~ (output point, integer to print, base to print in, width to zero-pad to
+~  -- output point)
+: pack-base-unsigned
+  3unroll swap 2dup logfloor 1 +
+  4 roll 2dup > {
+    swap drop
+  } {
+    drop
+  } if-else
+
+  {
+    ~ (output point, base, input, number of digits remaining)
+    2dup 1 -
+    5 roll dup 6 unroll swap
+    pow /% swap drop
+    4 roll dup 5 unroll
+    /% drop
+
+    dup 10 > {
+      0x30                                         ~ ASCII "0"
+    } {
+      10 - 0x61                                    ~ ASCII "a"
+    } if-else
+    +
+    ~ (output point, base, input, number of digits remaining, character)
+    5 roll swap pack8 4 unroll
+
+    1 -
+    dup { drop drop drop exit } unless
+  } forever ;
+
+
+~ (output point, integer to print, base to print in -- output point)
+: pack-base
+  swap
+
+  dup 0 > {
+    -1 *
+    3roll s" -" packstring 3unroll
+  } if
+
+  swap 0 .base-unsigned ;
+
+
+~ (output point, integer to print -- output point)
+: pack-decimal 10 pack-base ;
+: pack-hex 16 0 pack-base-unsigned ;
+: pack-hex8 16 2 pack-base-unsigned ;
+: pack-hex16 16 4 pack-base-unsigned ;
+: pack-hex32 16 8 pack-base-unsigned ;
+: pack-hex64 16 16 pack-base-unsigned ;
+
+~ (output point, integer to print, width -- output point)
+: pack-hexn 16 swap pack-base-unsigned ;