summary refs log tree commit diff
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@irenes.space>2026-05-15 14:11:09 -0700
committerIrene Knapp <ireneista@irenes.space>2026-05-15 14:11:09 -0700
commit13ec0a067a70ee1e5c0a287972c2f9f07d4e1486 (patch)
tree59e9c561d258cd27b6fe1121ce155e97b7787ae2
parent2cf147357ce578c3bc589b894930c71d709022e1 (diff)
transform runs inside the label loop now, and is able to do compilation
wow! yes. good. now it needs to actually generate label calls :)

Force-Push: yes
Change-Id: Ide4336e00aa6860fe55c956063303edc873c6d9b
-rw-r--r--evoke.e9
-rw-r--r--transform.e88
2 files changed, 60 insertions, 37 deletions
diff --git a/evoke.e b/evoke.e
index f6052a5..8a024ce 100644
--- a/evoke.e
+++ b/evoke.e
@@ -1,6 +1,14 @@
 ~ cat labels.e elf.e execution.e transform.e evoke.e \
 ~     | ./quine > evoke && chmod 755 evoke && ./evoke
 
+1024 read-to-buffer
+: foo 5 . [ 4 . ] ;
+pyrzqxgl
+s" source-to-precompile" variable
+
+~ (output memory start, current output point
+~  -- output memory start, current output point)
+
 ~ (output memory start, current output point
 ~  -- output memory start, current output point)
 ~
@@ -12,6 +20,7 @@
   cold-start
   warm-start
   output-docol
+  source-to-precompile transform
   0 L!' final-word-name
   current-offset L!' total-size
   ;
diff --git a/transform.e b/transform.e
index 7226ff1..a34e4a2 100644
--- a/transform.e
+++ b/transform.e
@@ -80,8 +80,13 @@
   ; make-immediate
   ~ TODO probably needs to do more
 
-8 allocate s" transform-state" variable
-0 transform-state !
+: transform-state-saved-here ;
+: transform-state-saved-latest 8 + ;
+: allocate-transform-state
+  2 8 * allocate
+  dup transform-state-saved-here 0 swap !
+  dup transform-state-saved-latest 0 swap ! ;
+allocate-transform-state s" transform-state" variable
 
 ~   We allow immediate words to run, which means for example that flow-control
 ~ hexdump-between words such as if-else expect to be able to mutate the heap,
@@ -91,9 +96,8 @@
 ~ ",".
 ~
 ~ (-- done)
-: transform-inner
+: transform-one
   word
-  ." wrapped here " here @ .hex64 newline
 
   ~ If no word was returned, exit.
   dup 0 = { drop 0 exit } if
@@ -105,11 +109,8 @@
 
   ~ If it's the magic word, end the transformation.
   dup s" pyrzqxgl" stringcmp 0 = { drop dropstring 1 exit } if
-  ." flags " interpreter-flags @ . newline
-  ." transformed: " dup emitstring newline
 
-  ~ Otherwise, look it up to see what it means.
-  find
+  transform-state transform-state-saved-latest @ swap find-in
 
   ~ Check whether the word was found in the dictionary.
   dup 0 != {
@@ -122,11 +123,11 @@
       dup entry-flags@ 1 & 0 =
 
       ~ ... but it's a regular word, so append it to the heap.
-      { entry-to-execution-token . 0 exit } if
+      ~ TODO why is ; being treated as a regular word
+      { entry-to-execution-token , 0 exit } if
     } if
 
     ~ ... if we're in interpret mode, or the word is immediate, run it.
-    ." stack before immediate word " stackhex
     entry-to-execution-token execute 0 exit
   } if
 
@@ -141,6 +142,7 @@
       ~ heap. The version of "lit" we use is the one that's current when we
       ~ ourselves are compiled, hardcoded; doing a dynamic lookup would
       ~ require dealing with what happens if it's not found.
+      ~ TODO this is wrong
       dropstring-with-result
       [ ' lit entry-to-execution-token literal ]
       , ,
@@ -150,39 +152,20 @@
     ~ We're in interpret mode; push the number to the stack. Or at least, that's
     ~ what the code we're interpreting will see. Really it's already on the
     ~ stack, just clean everything else up and leave it there.
-    dropstring-with-result 0 exit
+    dropstring-with-result
+    0 exit
   } if
 
   ~ If it's neither in the dictionary nor a number, just print an error.
   s" No such word: " emitstring value@ emitstring dropstring 0 ;
 
-~ (output point -- output point, done)
-: transform-one
-  ~ Save the old value of "here", and set it to our output point.
-  here @ transform-state ! here !
-  ~ Now the stack has nothing of ours on it, so client code can do its thing.
-
-  ~ Invoke client code.
-  transform-inner
-  ~ (done)
-
-  ~ Swap them back.
-  here @ transform-state @ here !
-
-  ~ While we don't actually use transform-state outside of this invocation,
-  ~ for tidiness we zero it out.
-  0 transform-state !
-
-  swap ;
-
-
 
 ~ ." input " main-input-buffer dup .hex64 newline dup hexdump @ dup .hex64 newline bye
 ~ 1024 read-to-buffer
 ~ foo bar baz biff
 ~ pyrzqxgl
 ~ stackhex dup hexdump emitstring bye
-~ 
+~
 ~ : breakza
 ~   ." original" newline
 ~   main-input-buffer dup 6 8 * hexdump-from
@@ -199,17 +182,48 @@
 ~   stackhex
 ~   bye ;
 
-~ (output point -- output point)
+~ (output point, input string pointer -- output point)
 : transform
-  1024 read-to-buffer ." transformation input buffer" newline dup hexdump
-  ~ (output point, string pointer)
-
   main-input-buffer dup push-input-buffer
   ~ TODO the arguments for this seem to be backwards from the documentation
   swap attach-string-to-input-buffer
 
+  ~ Set the initial inner value of "latest".
+  0 transform-state transform-state-saved-latest !
+
+  ~   Save the old values of "here" and "latest", and set the initial values
+  ~ of the internal ones. These values need to persist across iterations,
+  ~ since client code will make its own updates to them and then rely on those
+  ~ updates having taken effect. So we do the swap just once, here outside the
+  ~ loop, and set it back when the loop ends.
+  here @ transform-state transform-state-saved-here !
+  latest @ transform-state transform-state-saved-latest !
+  here !
+  0 latest !
+  ~ Now the stack has nothing of ours on it, so client code can do its thing.
+
+  ~   It's important that the stack has nothing of ours on it that persists
+  ~ across iterations, so that client code can add and remove stuff there as
+  ~ it sees fit.
   { transform-one
-    { main-input-buffer pop-input-buffer
+    ~ (done)
+
+    ~  When the loop is done, get the real values of "here" and "latest"
+    ~ back. The internal "here" is also the output point, and will become our
+    ~ return value. The internal "latest" is discarded.
+    { here @
+      transform-state transform-state-saved-here @ here !
+      transform-state transform-state-saved-latest @ latest !
+      ~ (output point)
+
+      ~   Though we don't actually use transform-state outside of this
+      ~ invocation, for tidiness we zero it out.
+      0 transform-state transform-state-saved-here !
+      0 transform-state transform-state-saved-latest !
+
+      ~  Also put the input source back how it was.
+      main-input-buffer pop-input-buffer
+
       exit } if } forever ;
 
 ~ 1024 allocate dup