diff options
| -rw-r--r-- | quine.asm | 391 |
1 files changed, 257 insertions, 134 deletions
diff --git a/quine.asm b/quine.asm index c5148ef..0a5d96d 100644 --- a/quine.asm +++ b/quine.asm @@ -4,6 +4,12 @@ ;;; ;;; There's some tabular information, but diagrams have been avoided, in an ;;; attempt to make this manageable in screen readers. Feedback welcome. +;;; +;;; First the hex +;;; Second the spark +;;; Third the words +;;; Then tie the knot +;;; [draft] ;;;;;;;;;;;;;;;;;;;;; @@ -2902,6 +2908,24 @@ cold_start: dq hlt dq lit, 8, packalign, early_here_store + ; This was "align_size". + dq litstring, "align-size", early_create, early_docol_codeword + dq litstring, "dup", early_find, entry_to_execution_token, early_comma + dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma + dq litstring, "dup", early_find, entry_to_execution_token, early_comma + dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 1, early_comma + dq litstring, "-", early_find, entry_to_execution_token, early_comma + dq litstring, "+", early_find, entry_to_execution_token, early_comma + dq litstring, "swap", early_find, entry_to_execution_token, early_comma + dq litstring, "/%", early_find, entry_to_execution_token, early_comma + dq litstring, "swap", early_find, entry_to_execution_token, early_comma + dq litstring, "drop", early_find, entry_to_execution_token, early_comma + dq litstring, "*", early_find, entry_to_execution_token, early_comma + dq litstring, "exit", early_find, entry_to_execution_token, early_comma + dq early_here, fetch, lit, 8, packalign, early_here_store + ; We could in theory call this 64pack, by analogy to 32! and so on, but it's ; kept like this to be more similar to reg64, imm64 etc. ; @@ -3078,7 +3102,8 @@ cold_start: dq early_here, fetch, lit, 8, packalign, early_here_store dq litstring, "unpackalign", early_create, early_docol_codeword - dq litstring, "packalign", early_find, entry_to_execution_token, early_comma + dq litstring, "align-size", early_find, entry_to_execution_token + dq early_comma dq litstring, "exit", early_find, entry_to_execution_token, early_comma dq early_here, fetch, lit, 8, packalign, early_here_store @@ -6469,74 +6494,159 @@ cold_start: dq litstring, "exit", early_find, entry_to_execution_token, early_comma dq early_here, fetch, lit, 8, packalign, early_here_store - ;;; As a convenience for "word", we have some facilities for working with + + ;;; As a convenience for "word", we have some facilities for working with ;;; stack-allocated strings. Yeah, trippy concept. Also, it would be a ;;; buffer overrun hazard if we were worried about that, which is why this ;;; is no longer common practice in C. - dq litstring, "stack-allocate-string-accumulator", early_create - dq early_docol_codeword + ;;; + ;;; The most important of these is accumulate-string, but we need some + ;;; smaller pieces first. + + ; In: + ; (multiple words) string + ; (multiple words) items to be left alone + ; item to be unrolled + ; number of items above string that participate in the unroll + ; Out: + ; item that was unrolled + ; (multiple words) string + ; (multiple words) items left alone + dq litstring, "unroll-past-string", early_create, early_docol_codeword dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0, early_comma + dq lit, 8, early_comma + dq litstring, "*", early_find, entry_to_execution_token, early_comma + ; (string, other items, top item, byte offset to string start) + dq litstring, "dup", early_find, entry_to_execution_token, early_comma dq litstring, "value@", early_find, entry_to_execution_token, early_comma + dq litstring, "+", early_find, entry_to_execution_token, early_comma + ; We have two copies of the offset present, in addition to the stuff we want + ; to rotate. So, the actual string starts two words on... We could have + ; adjusted the offset instead, but we'll want the unmodified offset again + ; later. + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 16, early_comma + dq litstring, "+", early_find, entry_to_execution_token, early_comma + ; (string, other items, top item, offset to start, string pointer) + dq litstring, "stringlen", early_find, entry_to_execution_token, early_comma + ; Same reasoning as in accumulate-string (see below). + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 1, early_comma + dq litstring, "+", early_find, entry_to_execution_token, early_comma + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 8, early_comma + dq litstring, "align-size", early_find, entry_to_execution_token, early_comma + ; (string, other items, top item, offset to start, string length w/ padding) + dq litstring, "+", early_find, entry_to_execution_token, early_comma + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 8, early_comma + dq litstring, "/%", early_find, entry_to_execution_token, early_comma + dq litstring, "swap", early_find, entry_to_execution_token, early_comma + dq litstring, "drop", early_find, entry_to_execution_token, early_comma + ; (string, other items, top item, number of words to unroll) + dq litstring, "unroll", early_find, entry_to_execution_token, early_comma dq litstring, "exit", early_find, entry_to_execution_token, early_comma dq early_here, fetch, lit, 8, packalign, early_here_store - dq litstring, "stack-deallocate-string-accumulator", early_create - dq early_docol_codeword + ; In: + ; (multiple words) string + ; item to be swapped + ; Out: + ; item that was swapped + ; (multiple words) string + dq litstring, "swap-past-string", 0, early_create, early_docol_codeword + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 1, early_comma + dq litstring, "unroll-past-string", early_find, entry_to_execution_token + dq early_comma + dq litstring, "exit", early_find, entry_to_execution_token, early_comma + dq early_here, fetch, lit, 8, packalign, early_here_store + + ; In: + ; (multiple words) string + dq litstring, "dropstring", early_create, early_docol_codeword + dq litstring, "value@", early_find, entry_to_execution_token, early_comma + dq litstring, "stringlen", early_find, entry_to_execution_token, early_comma + ; Same reasoning as in accumulate-string (see below). + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 1, early_comma + dq litstring, "+", early_find, entry_to_execution_token, early_comma + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 8, early_comma + dq litstring, "align-size", early_find, entry_to_execution_token, early_comma + dq litstring, "value@", early_find, entry_to_execution_token, early_comma + dq litstring, "+", early_find, entry_to_execution_token, early_comma + ; At the time we fetched the stack pointer, there was an extra value atop + ; it, so we have to add one more word. + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 8, early_comma + dq litstring, "+", early_find, entry_to_execution_token, early_comma dq litstring, "value!", early_find, entry_to_execution_token, early_comma - dq litstring, "drop", early_find, entry_to_execution_token, early_comma dq litstring, "exit", early_find, entry_to_execution_token, early_comma dq early_here, fetch, lit, 8, packalign, early_here_store ; In: ; (multiple words) string - ; pointer to start of string - ; result + ; item to be kept ; Out: - ; result - dq litstring, "stack-deallocate-string-accumulator-with-result" - dq early_create, early_docol_codeword - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "!", early_find, entry_to_execution_token, early_comma - dq litstring, "value!", early_find, entry_to_execution_token, early_comma + ; item that was kept + dq litstring, "dropstring-with-result", early_create, early_docol_codeword + dq litstring, "swap-past-string", 0, early_find, entry_to_execution_token + dq early_comma + dq litstring, "dropstring", early_find, entry_to_execution_token + dq early_comma dq litstring, "exit", early_find, entry_to_execution_token, early_comma dq early_here, fetch, lit, 8, packalign, early_here_store ; In: ; (multiple words) string-so-far - ; pointer to start of string-so-far ; new character byte ; Out: - ; updated string-so-far - ; pointer to start of string-so-far - dq litstring, "accumulate-string", early_create, early_docol_codeword + ; (multiple words) updated string-so-far + dq litstring, "accumulate-string", early_create + dq early_docol_codeword - ; Examine the final word of the string, leaving other stuff undisturbed. - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma + ; Compute the address of the final word of the string. + ; + ; It's a little bit difficult to get the start pointer right, since all + ; our intermediate products affect what we get from value@, so we compute + ; that just once, here at the beginning. + dq litstring, "value@", early_find, entry_to_execution_token, early_comma + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 8, early_comma + dq litstring, "+", early_find, entry_to_execution_token, early_comma + ; (string so far, new character byte, pointer to start of string) dq litstring, "dup", early_find, entry_to_execution_token, early_comma + dq litstring, "stringlen", early_find, entry_to_execution_token, early_comma + ; There are two concerns here that overlap: First, we always want at least + ; one word. Recall that a length of zero bytes won't receive any alignment + ; padding because it's already divisible by 8. Second, the result of + ; stringlen doesn't include the null byte, which might be in a word by + ; itself that needs to be counted. We can address both of them by + ; unconditionally adding 1 to the length before applying alignment. dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma + dq lit, 1, early_comma + dq litstring, "+", early_find, entry_to_execution_token, early_comma + ; Pad the length for alignment. dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 0xFF00000000000000, early_comma - dq litstring, "and", early_find, entry_to_execution_token, early_comma - dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 3*8, early_comma - - ; If the top byte of the final word of the string is occupied, we need to - ; start a new word. Our representation makes that trivial. - dq litstring, "swap", early_find, entry_to_execution_token, early_comma - dq litstring, "exit", early_find, entry_to_execution_token, early_comma + dq lit, 8, early_comma + dq litstring, "align-size", early_find, entry_to_execution_token + dq early_comma + ; We want an offset from the first word of the string to the last word of + ; the string, so we subtract one word from the length. + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 8, early_comma + dq litstring, "-", early_find, entry_to_execution_token, early_comma + dq litstring, "+", early_find, entry_to_execution_token, early_comma + ; (string so far, new character byte, address of final word) - ; If the top byte is unoccupied, figure out where to store the new byte. - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma + ; Examine the final word of the string, leaving other stuff undisturbed. + ; Work low-to-high to figure out where to store the new byte, taking the + ; first one that's available. + ; (string so far, new character byte, address of final word) + dq litstring, "dup", early_find, entry_to_execution_token, early_comma + dq litstring, "@", early_find, entry_to_execution_token, early_comma dq litstring, "dup", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0x00000000000000FF, early_comma dq litstring, "and", early_find, entry_to_execution_token, early_comma @@ -6544,144 +6654,177 @@ cold_start: dq lit, 0, early_comma dq litstring, "=", early_find, entry_to_execution_token, early_comma dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 5*8, early_comma + dq lit, 6*8, early_comma + ; (string so far, new character byte, address of final word, old value) dq litstring, "3roll", early_find, entry_to_execution_token, early_comma dq litstring, "or", early_find, entry_to_execution_token, early_comma dq litstring, "swap", early_find, entry_to_execution_token, early_comma + dq litstring, "!", early_find, entry_to_execution_token, early_comma dq litstring, "exit", early_find, entry_to_execution_token, early_comma + ; (string so far, new character byte, address of final word, old value) - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma + ; This next part is repeated several times, changing only the offsets, for + ; bytes 1 through 6; bytes 0 (above) and 7 (way below) are different. + ; (string so far, new character byte, address of final word, old value) dq litstring, "dup", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0x000000000000FF00, early_comma dq litstring, "and", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0, early_comma dq litstring, "=", early_find, entry_to_execution_token, early_comma dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma + dq lit, 9*8, early_comma + ; (string so far, new character byte, address of final word, old value) + dq litstring, "3roll", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0x0000000000000100, early_comma dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma dq litstring, "or", early_find, entry_to_execution_token, early_comma dq litstring, "swap", early_find, entry_to_execution_token, early_comma + dq litstring, "!", early_find, entry_to_execution_token, early_comma dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma + ; Highly repetitive code, see above. + ; (string so far, new character byte, address of final word, old value) dq litstring, "dup", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0x0000000000FF0000, early_comma dq litstring, "and", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0, early_comma dq litstring, "=", early_find, entry_to_execution_token, early_comma dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma + dq lit, 9*8, early_comma + ; (string so far, new character byte, address of final word, old value) + dq litstring, "3roll", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0x0000000000010000, early_comma dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma dq litstring, "or", early_find, entry_to_execution_token, early_comma dq litstring, "swap", early_find, entry_to_execution_token, early_comma + dq litstring, "!", early_find, entry_to_execution_token, early_comma dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma + ; Highly repetitive code, see above. + ; (string so far, new character byte, address of final word, old value) dq litstring, "dup", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0x00000000FF000000, early_comma dq litstring, "and", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0, early_comma dq litstring, "=", early_find, entry_to_execution_token, early_comma dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma + dq lit, 9*8, early_comma + ; (string so far, new character byte, address of final word, old value) + dq litstring, "3roll", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0x0000000001000000, early_comma dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma dq litstring, "or", early_find, entry_to_execution_token, early_comma dq litstring, "swap", early_find, entry_to_execution_token, early_comma + dq litstring, "!", early_find, entry_to_execution_token, early_comma dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma + ; Highly repetitive code, see above. + ; (string so far, new character byte, address of final word, old value) dq litstring, "dup", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0x000000FF00000000, early_comma dq litstring, "and", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0, early_comma dq litstring, "=", early_find, entry_to_execution_token, early_comma dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma + dq lit, 9*8, early_comma + ; (string so far, new character byte, address of final word, old value) + dq litstring, "3roll", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0x0000000100000000, early_comma dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma dq litstring, "or", early_find, entry_to_execution_token, early_comma dq litstring, "swap", early_find, entry_to_execution_token, early_comma + dq litstring, "!", early_find, entry_to_execution_token, early_comma dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma + ; Highly repetitive code, see above. + ; (string so far, new character byte, address of final word, old value) dq litstring, "dup", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0x0000FF0000000000, early_comma dq litstring, "and", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0, early_comma dq litstring, "=", early_find, entry_to_execution_token, early_comma dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma + dq lit, 9*8, early_comma + ; (string so far, new character byte, address of final word, old value) + dq litstring, "3roll", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0x0000010000000000, early_comma dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma dq litstring, "or", early_find, entry_to_execution_token, early_comma dq litstring, "swap", early_find, entry_to_execution_token, early_comma + dq litstring, "!", early_find, entry_to_execution_token, early_comma dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma + ; Highly repetitive code, see above. + ; (string so far, new character byte, address of final word, old value) dq litstring, "dup", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma - dq lit, 4, early_comma - dq litstring, "unroll", early_find, entry_to_execution_token, early_comma - dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0x00FF000000000000, early_comma dq litstring, "and", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0, early_comma dq litstring, "=", early_find, entry_to_execution_token, early_comma dq litstring, "0branch", early_find, entry_to_execution_token, early_comma - dq lit, 8*8, early_comma + dq lit, 9*8, early_comma + ; (string so far, new character byte, address of final word, old value) + dq litstring, "3roll", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0x0001000000000000, early_comma dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma dq litstring, "or", early_find, entry_to_execution_token, early_comma dq litstring, "swap", early_find, entry_to_execution_token, early_comma + dq litstring, "!", early_find, entry_to_execution_token, early_comma dq litstring, "exit", early_find, entry_to_execution_token, early_comma + ; The top byte of the final word is always zero (or else stringlen + ; wouldn't have called it the final word), so we don't need to check it, we + ; can just use it. + ; + ; We need to put the new value in the top byte, which will mean we have no + ; null terminator, so we also need to start a new word. + ; + ; There is a fiddly order-dependency here: unroll-past-string relies on + ; being able to find the null terminator, which won't work if we've gotten + ; rid of it. Also, calling it will move all the earlier words, including + ; the one we intend to write to, which will invalidate any pointer we're + ; keeping at that point. There's a few ways to resolve this; what we do is + ; put the new terminator in place first, manually nudge the pointer, and + ; then write the new value. + ; (string so far, new character byte, address of final word, old value) + dq litstring, "3roll", early_find, entry_to_execution_token, early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0x0100000000000000, early_comma dq litstring, "*", early_find, entry_to_execution_token, early_comma - dq litstring, "3roll", early_find, entry_to_execution_token, early_comma dq litstring, "or", early_find, entry_to_execution_token, early_comma dq litstring, "swap", early_find, entry_to_execution_token, early_comma + ; (string so far, new value, address of final word) + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 0, early_comma + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 3, early_comma + dq litstring, "unroll-past-string", early_find, entry_to_execution_token + dq early_comma + ; (new null terminator, string so far, new value, invalid address) + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 8, early_comma + dq litstring, "-", early_find, entry_to_execution_token, early_comma + ; (new null terminator, string so far, new value, updated address) + dq litstring, "!", early_find, entry_to_execution_token, early_comma + ; (updated string) dq litstring, "exit", early_find, entry_to_execution_token, early_comma dq early_here, fetch, lit, 8, packalign, early_here_store @@ -6690,13 +6833,12 @@ cold_start: ; ; Out: ; (multiple words) string - ; pointer to start of string dq litstring, "word", early_create, early_docol_codeword - ; We allocate this first, so that the result of "key" wil conveniently be - ; on the easy-to-find end of it. - dq litstring, "stack-allocate-string-accumulator", early_find - dq entry_to_execution_token, early_comma + ; We allocate an empty string first, so that the result of "key" will + ; conveniently be on the easy-to-find end of it. + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 0, early_comma ; Skip whitespace. dq litstring, "key", early_find, entry_to_execution_token, early_comma @@ -6715,8 +6857,8 @@ cold_start: dq litstring, "0branch", early_find, entry_to_execution_token, early_comma dq lit, 6*8, early_comma dq litstring, "drop", early_find, entry_to_execution_token, early_comma - dq litstring, "stack-deallocate-string-accumulator", early_find - dq entry_to_execution_token, early_comma + dq litstring, "dropstring", early_find, entry_to_execution_token + dq early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma dq lit, 0, early_comma dq litstring, "exit", early_find, entry_to_execution_token, early_comma @@ -6940,7 +7082,10 @@ cold_start: dq litstring, "drop", early_find, entry_to_execution_token, early_comma dq litstring, "exit", early_find, entry_to_execution_token, early_comma - dq litstring, "dup", early_find, entry_to_execution_token, early_comma + ; The string is on the top of the stack, so to get a pointer to it we get + ; the stack address. + ; (string) + dq litstring, "value@", early_find, entry_to_execution_token, early_comma dq litstring, "find", early_find, entry_to_execution_token, early_comma ; Check whether the word was found in the dictionary. @@ -6952,8 +7097,8 @@ cold_start: dq lit, 6*8, early_comma ; If the word is in the dictionary, run it. - dq litstring, "stack-deallocate-string-accumulator-with-result", early_find - dq entry_to_execution_token, early_comma + dq litstring, "dropstring-with-result", early_find, entry_to_execution_token + dq early_comma dq litstring, "entry-to-execution-token", 0, early_find dq entry_to_execution_token, early_comma dq litstring, "execute", early_find, entry_to_execution_token, early_comma @@ -6963,8 +7108,9 @@ cold_start: ; If it's not in the dictionary, check whether it's a decimal number. dq litstring, "drop", early_find, entry_to_execution_token, early_comma - ; (string contents..., string pointer) - dq litstring, "dup", early_find, entry_to_execution_token, early_comma + ; As before, we get the stack address and use it as a string pointer. + ; (string) + dq litstring, "value@", early_find, entry_to_execution_token, early_comma dq litstring, "read-decimal", early_find, entry_to_execution_token dq early_comma dq litstring, "lit", early_find, entry_to_execution_token, early_comma @@ -6976,15 +7122,15 @@ cold_start: ; It's a number; push it 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. - dq litstring, "stack-deallocate-string-accumulator-with-result", early_find - dq entry_to_execution_token, early_comma + dq litstring, "dropstring-with-result", early_find, entry_to_execution_token + dq early_comma dq litstring, "branch", early_find, entry_to_execution_token, early_comma ; o/~ Like a whirlpool and it never ends. o/~ dq lit, -32*8, early_comma ; If it's neither in the dictionary nor a number, exit. - dq litstring, "stack-deallocate-string-accumulator", early_find - dq entry_to_execution_token, early_comma + dq litstring, "dropstring", early_find, entry_to_execution_token + dq early_comma dq litstring, "litstring", early_find, entry_to_execution_token, early_comma dq lit, "No such ", early_comma, lit, "word.", early_comma dq litstring, "emitstring", early_find, entry_to_execution_token @@ -6993,6 +7139,7 @@ cold_start: dq early_here, fetch, lit, 8, packalign, early_here_store + ; The next layer is built now, so let's move on to it. dq litstring, "interpret", early_find, entry_to_execution_token ; Get rid of that heap pointer on the stack, we're finally done with it! @@ -7003,42 +7150,6 @@ cold_start: dq lit, 1, sys_exit - ;;; TODO rethink this, it needs to not use space on the value stack - ;; Stack-allocate a buffer. - ;; - ;; For brevity's sake, in notation below here when we give the contents of - ;; the stack we'll leave out the original copy of the heap pointer, and the - ;; four words used for the buffer. - ;dq lit, 0, lit, 0, lit, 0, lit, 0, fetch_value_stack - ;; Make a copy of the heap pointer so we can have it a little closer. If we - ;; instead were to try to get to the copy on the other side of the buffer by - ;; rolling, it would move the buffer, invalidating the pointers. - ;dq lit, 6, roll, dup, lit, 7, unroll, swap - ;dq dup - ;dq lit, boot_source - ;; (heap pointer, buffer start pointer, buffer end pointer, input pointer) - ; - ;; Start of the loop - ;dq key ; 1 word - ; - ;; (heap pointer, buffer start pointer, buffer end pointer, - ;; input pointer, input byte) - ;dq dup, lit, " ", ne, zbranch, 13*8 ; 6 words - ;dq dup, lit, 0x0a, ne, zbranch, 7*8 ; 6 words - ; - ;; If we got here, it's a body character. - ;dq roll3, swap, pack8, swap, branch, -18*8 ; 6 words - ; - ;; If we got here, it's a space character. - ;dq drop, swap, lit, 0, pack8 ; 5 words - ;dq swap, roll3, dup, lit, 4, unroll ; 6 words - ; - ;; (heap pointer, buffer start pointer, buffer end pointer, - ;; input pointer, word pointer) - ;dq lit, 5, roll, swap, early_find, swap, lit, 5, unroll ; 8 words - ;dq entry_to_execution_token, execute ; 2 words - ;dq branch, -41*8 - ;;; For triage's sake, here's an inventory of everything else in the file. ;;; ;;; Macros: @@ -8504,6 +8615,18 @@ defword litpack8, 0 ;;; which it updates to point after the data item being read. Since this is ;;; input, the routines return data items rather than accepting them. +; In: +; proposed size +; alignment +; Out: +; adjusted size +defword align_size, 0 + dq docol + dq dup, unroll3, dup, unroll3 + ; (alignment, proposed size, alignment) + dq lit, 1, sub, add, swap, divmod, swap, drop, mul + dq exit + ; In: base address ; Out: new base address, value defword unpack64, 0 @@ -8523,8 +8646,8 @@ defword unpack8, 0 dq dup, fetch8, swap, lit, 1, add, swap dq exit -; Since there's no data, this is identical to its output version, but we -; allow this name as an alias for clarity. +; You might think this would be identical to packalign, but packalign has +; side effects. ; ; Stack in: ; base address @@ -8532,7 +8655,7 @@ defword unpack8, 0 ; Stack out: ; new base address defword unpackalign, 0 - dq docol, packalign, exit + dq docol, align_size, exit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |