diff --git a/evoke.e b/evoke.e
index df59a2a..4252e91 100644
--- a/evoke.e
+++ b/evoke.e
@@ -10,6 +10,8 @@ s" source-to-precompile" variable
~ : fooze 4 . ; fooze
1024 read-to-buffer
+~ We begin by outputting the actual docol routine, the one that codewords
+~ should point to. Note that this is before we've done any word header.
here @
dup L!' docol-codeword-value
:rsi pack-pushcontrol
@@ -19,20 +21,37 @@ pack-next
8 packalign
here !
-: docol
- [ here @
- L@' docol-codeword-value :rax mov-reg64-imm64
- :rax push-reg64
- here ! ] ;asm
+~ We can't use colon to create docol, not even the part that's a word,
+~ because colon tries to dynamically invoke docol to fill in the codeword.
+s" docol" create
+here @
+dup 8 + pack64
+L@' docol-codeword-value :rax mov-reg64-imm64
+:rax push-reg64
+pack-next
+8 packalign
+here !
+
-: exit
- [ here @
- :rsi pack-popcontrol
- here ! ] ;asm
+s" exit" create
+here @
+dup 8 + pack64
+:rsi pack-popcontrol
+here !
+
+: foo [ crash 1 2 + ;
-: foo 1 2 + ;
0 sys-exit
+
+~ Now that we have docol, colon will work and we can define exit the normal
+~ way.
+~ : exit
+~ [ here @
+~ :rsi pack-popcontrol
+~ here ! ] ;asm
+
pyrzqxgl
+~ 0 sys-exit
s" source-to-copy-to-log" variable
~ (output memory start, current output point
diff --git a/transform.e b/transform.e
index 7af668b..581cb0b 100644
--- a/transform.e
+++ b/transform.e
@@ -312,11 +312,14 @@ allocate-transform-state s" transform-state" variable
: describe-transformation
- ." active here " here @ .hex64 space ." latest " latest @ .hex64 newline
- ." saved here " transform-state transform-state-saved-here
+ ." active here " here @ .hex64 space
+ ." latest " latest @ .hex64 newline
+ ." saved here " transform-state transform-state-saved-here
@ .hex64 space
." latest " transform-state transform-state-saved-latest @ .hex64 newline
- ." output start " transform-state transform-state-output-buffer-start
+ ." output start " transform-state transform-state-output-buffer-start
+ @ .hex64 newline
+ ." user stack depth " transform-state transform-state-user-stack-depth
@ .hex64 newline ;
@@ -1464,12 +1467,14 @@ allocate-transform-state s" transform-state" variable
~ As usual, we do these in reverse.
L@' log-load-comma
L@' log-load-comma
+ L@' log-load-find-execution-token
L@' litstring
swap-transform-variables
~ The overall stack delta of this sequence is 0.
offset-to-target-address-space , ~ litstring
here @ s" lit" packstring 8 packalign here !
+ offset-to-target-address-space , ~ log-load-find-execution-token
offset-to-target-address-space , ~ log-load-comma
swap , ~ the value
offset-to-target-address-space , ~ log-load-comma
@@ -1482,24 +1487,27 @@ allocate-transform-state s" transform-state" variable
~ creating an entry on the log directly, its job is to output words which,
~ when they're later executed, will do create's job.
~
-~ The implementations of log-load-find-execution-token and log-load-create
-~ are in log-load.e.
+~ In practice that means outputting a codeword pointer to run a
+~ statically-compiled word that does the work. The implementation of
+~ log-load-create is in log-load.e.
~
-~ (string pointer --)
+~ It's worth keeping in mind that this alternate only gets called for
+~ manual invocations of "create". It isn't called from the colon alternate.
: log-load-create-alternate
log-load-roll-log-address
swap-transform-variables
- ~ Just like in log-load-compile-dynamic-word, we do this in reverse.
L@' log-load-create
- L@' litstring
+ L@' swap
swap-transform-variables
~ The overall stack delta of this sequence is 0.
- offset-to-target-address-space , ~ litstring
- swap here @ swap packstring 8 packalign here !
+ offset-to-target-address-space , ~ swap
offset-to-target-address-space , ~ log-load-create
+ ~ We've consumed a string pointer from the stack, so that's a delta of -1.
+ -1 transform-apply-stack-delta
+
log-load-unroll-log-address ;
@@ -1508,8 +1516,25 @@ allocate-transform-state s" transform-state" variable
~ to be extremely useful to read and understand ":" in interpret.e before
~ attempting to understand "log-load-colon-alternate".
: log-load-colon-alternate
- ~ This calls "log-load-create" instead of "create".
- word value@ log-load-create-alternate dropstring
+ word value@
+
+ ~ Calling log-load-create-alternate would result in some redundant rolling
+ ~ and unrolling, so we do it together like this instead.
+ log-load-roll-log-address
+
+ swap-transform-variables
+ L@' log-load-create
+ L@' litstring
+ swap-transform-variables
+
+ ~ The overall stack delta of this sequence is 0.
+ offset-to-target-address-space , ~ litstring
+ swap here @ swap packstring 8 packalign here !
+ offset-to-target-address-space , ~ log-load-create
+
+ log-load-unroll-log-address
+
+ dropstring
~ We generate code that looks up "docol" by name, runs it to get the
~ codeword pointer, then finally appends it to the entry.
@@ -1575,6 +1600,65 @@ allocate-transform-state s" transform-state" variable
; make-immediate
+~ This just does the same thing [ always does, but having it as an alternate
+~ means it happens at transformation time, which is sooner than "immediate"
+~ time. The log load transform is weird like that, it has three different
+~ times things can happen, rather than the usual two.
+: log-load-left-square-brace-alternate
+ ~ Since [ is an immediate word, we have to go to extra trouble to compile
+ ~ it as part of the alternate.
+ [ ' [ entry-to-execution-token , ]
+ ; make-immediate
+
+~ We need this one, too. It's not even an immediate word normally!
+: log-load-right-square-brace-alternate ] ; make-immediate
+
+~ Yeah comments have to go.
+: log-load-tilde-alternate
+ ' ~ entry-to-execution-token execute
+ ; make-immediate
+
+~ Strings are important and must happen now, now, now.
+: log-load-string-alternate
+ ~ Something subtle here: s" is state-dependent. That is, it does different
+ ~ things depending on the interpreter flags. We would really rather know
+ ~ which version we're getting, and also it would be best if it didn't
+ ~ scribble on the output buffer. Fortunately we can achieve both of these,
+ ~ by coercing things into a known state while calling it.
+ ~
+ ~ We could choose either version of s", but the interpreted one is more
+ ~ convenient because it doesn't mess with a spurious litstring invocation,
+ ~ just scribbled into scratch space after "here". Of course, that raises the
+ ~ additional concern that we have the wrong "here", but we can just swap
+ ~ that around, too.
+ ~
+ ~ This is all worth it to avoid reimplementing s". If we had two
+ ~ implementations, they'd have to be kept in sync, and it's an important
+ ~ user-facing word with semantics that are likely to improve over time.
+ interpreter-flags @
+ ' s" entry-to-execution-token
+ swap-transform-variables
+ ~ Since [ is an immediate word, we have to go to extra trouble to compile
+ ~ it as part of the alternate.
+ [ ' [ entry-to-execution-token , ]
+ execute
+ swap-transform-variables
+ swap interpreter-flags !
+ ~ Whew. What a mouthful.
+ ~ (string pointer)
+
+ swap-transform-variables
+ L@' litstring
+ swap-transform-variables
+
+ offset-to-target-address-space , ~ litstring
+ here @ swap packstring 8 packalign here !
+
+ ~ Now the string pointer is on the stack, so we apply a delta for it.
+ 1 transform-apply-stack-delta
+ ; make-immediate
+
+
~ Because docol requires it, we provide a special mini-version of the label
~ system. We only do L@' and L!', because that's all we need. Unlike the
~ version of this feature for the label transform, for the log-load transform,
@@ -1663,6 +1747,15 @@ allocate-transform-state s" transform-state" variable
swap drop ' log-load-semicolon-alternate swap } if
dup s" ;asm" stringcmp 0 = {
swap drop ' log-load-semicolon-assembly-alternate swap } if
+ dup s" [" stringcmp 0 = {
+ swap drop ' log-load-left-square-brace-alternate swap } if
+ dup s" ]" stringcmp 0 = {
+ swap drop ' log-load-right-square-brace-alternate swap } if
+ dup s" ~" stringcmp 0 = {
+ swap drop ' log-load-tilde-alternate swap } if
+ ~ It is nontrivial to construct a string with a double-quote in it.
+ dup ' s" entry-to-name stringcmp 0 = {
+ swap drop ' log-load-string-alternate swap } if
dup s" L@'" stringcmp 0 = { swap drop ' log-load-L@'-alternate swap } if
dup s" L!'" stringcmp 0 = { swap drop ' log-load-L!'-alternate swap } if
~ (name as stack string, 0 or alternate entry pointer, name pointer)
|