From 13ec0a067a70ee1e5c0a287972c2f9f07d4e1486 Mon Sep 17 00:00:00 2001 From: Irene Knapp Date: Fri, 15 May 2026 14:11:09 -0700 Subject: 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 --- evoke.e | 9 +++++++ transform.e | 88 +++++++++++++++++++++++++++++++++++-------------------------- 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 -- cgit 1.4.1