From e20e90fde19dd94b1dce7a9b65eba77956d0213b Mon Sep 17 00:00:00 2001 From: Irene Knapp Date: Fri, 17 Apr 2026 13:31:13 -0700 Subject: some stuff for dealing with circular buffers, implemented as heap words by putting this directly on the heap, we allow it to work in the easy, obvious ways, at the cost of extreme verbosity. the core abstractions here are "buffer", "input buffer", and "buffer metadata". the metadata struct is distinct from the backing store, though there is a convenience word to allocate them together. for communication purposes, the buffer "is" the metadata struct, and the "backing store" is where things are actually read from. all input buffers are buffers but someday not all buffers will be input buffers; note carefully how the various word names make this distinction. Force-Push: yes Change-Id: Ib85a74af046b42c8959c6edf93b83e2ad7f21be4 --- quine.asm | 391 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 390 insertions(+), 1 deletion(-) (limited to 'quine.asm') diff --git a/quine.asm b/quine.asm index e9f15fd..4c68373 100644 --- a/quine.asm +++ b/quine.asm @@ -5871,7 +5871,367 @@ cold_start: dq litstring, "exit", early_find, entry_to_execution_token, early_comma dq early_here, fetch, lit, 8, packalign, early_here_store - dq early_describe_all, lit, 0, sys_exit + ;;; Now here we have some "original" words that rely on the heap and don't + ;;; have flatassembler-based equivalents. + + ; In: + ; name string + dq litstring, "create", early_create, early_docol_codeword + dq litstring, "here", early_find, entry_to_execution_token, early_comma + dq litstring, "@", early_find, entry_to_execution_token, early_comma + dq litstring, "latest", early_find, entry_to_execution_token, early_comma + dq litstring, "@", early_find, entry_to_execution_token, early_comma + dq litstring, "pack64", 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, "pack8", 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, "pack8", early_find, entry_to_execution_token, early_comma + dq litstring, "swap", early_find, entry_to_execution_token, early_comma + dq litstring, "packstring", early_find, entry_to_execution_token + dq early_comma + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 8, early_comma + dq litstring, "packalign", early_find, entry_to_execution_token, early_comma + dq litstring, "here", early_find, entry_to_execution_token, early_comma + dq litstring, "@", early_find, entry_to_execution_token, early_comma + dq litstring, "latest", early_find, entry_to_execution_token, early_comma + dq litstring, "!", early_find, entry_to_execution_token, early_comma + dq litstring, "here", 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 + + ; In: + ; value to append to current word-in-progress + dq litstring, ",", early_create, early_docol_codeword + dq litstring, "here", 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, "pack64", early_find, entry_to_execution_token, early_comma + dq litstring, "here", 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 + + dq litstring, "self-codeword", early_create, early_docol_codeword + dq litstring, "here", early_find, entry_to_execution_token, 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, "+", 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 + + ; In: + ; address for new variable word to return + ; name string + dq litstring, "variable", 0, early_create, early_docol_codeword + dq litstring, "create", early_find, entry_to_execution_token, early_comma + dq litstring, "self-codeword", early_find, entry_to_execution_token + dq early_comma + dq litstring, "here", 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, ":rax", early_find, entry_to_execution_token, early_comma + dq litstring, "mov-reg64-imm64", early_find, entry_to_execution_token + dq early_comma + dq litstring, ":rax", early_find, entry_to_execution_token, early_comma + dq litstring, "push-reg64", early_find, entry_to_execution_token + dq early_comma + dq litstring, "pack-next", 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, "packalign", early_find, entry_to_execution_token, early_comma + dq litstring, "here", 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 + + ; Allocates bytes on the heap by incrementing the global "here" pointer. + ; The "here" pointer is kept aligned to an 8-byte boundary, regardless of + ; the size requested. + ; + ; This does not create dictionary entries, it's just a raw memory + ; interface. It's suitable for allocating data or scratch space. + ; + ; In: + ; size in bytes + ; Out: + ; pointer to start + dq litstring, "allocate", 0, early_create, early_docol_codeword + dq litstring, "here", 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 + ; (size, here value, here value) + dq litstring, "3roll", early_find, entry_to_execution_token, 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, "packalign", early_find, entry_to_execution_token, early_comma + dq litstring, "here", 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 + + ; In: + ; pointer to buffer metadata + ; Out: + ; pointer to buffer "physical-start" field + dq litstring, "buffer-physical-start", early_create, early_docol_codeword + ; The physical-start field happens to be the first thing in the metadata, so + ; this is an nop, but it still exists as a word because having it reduces + ; confusion. + dq litstring, "exit", early_find, entry_to_execution_token, early_comma + dq early_here, fetch, lit, 8, packalign, early_here_store + + ; In: + ; pointer to buffer metadata + ; Out: + ; pointer to buffer "physical-end" field + dq litstring, "buffer-physical-end", early_create, early_docol_codeword + 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, "exit", early_find, entry_to_execution_token, early_comma + dq early_here, fetch, lit, 8, packalign, early_here_store + + ; In: + ; pointer to buffer metadata + ; Out: + ; pointer to buffer "logical-start" field + dq litstring, "buffer-logical-start", early_create, early_docol_codeword + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 2*8, 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 + + ; In: + ; pointer to buffer metadata + ; Out: + ; pointer to buffer "logical-end" field + dq litstring, "buffer-logical-end", early_create, early_docol_codeword + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 3*8, 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 + + ; In: + ; pointer to input buffer metadata + ; Out: + ; pointer to input buffer "refill" field + dq litstring, "input-buffer-refill", early_create, early_docol_codeword + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 4*8, 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 + + ; Given an initialized buffer (input or otherwise), sets its "start" and + ; "end" pointers to indicate the buffer is empty. This relies on the buffer + ; having a backing store attached, but does not alter the backing store or + ; its contents. + ; + ; In: + ; pointer to buffer metadata + dq litstring, "clear-buffer", early_create, early_docol_codeword + dq litstring, "dup", early_find, entry_to_execution_token, early_comma + dq litstring, "buffer-physical-start", early_find, entry_to_execution_token + dq 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, "3roll", early_find, entry_to_execution_token, early_comma + ; (address of backing store, address of backing store, metadata pointer) + dq litstring, "dup", early_find, entry_to_execution_token, early_comma + dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma + ; (address of backing store, metadata pointer, + ; address of backing store, metadata pointer) + dq litstring, "buffer-logical-start", early_find, entry_to_execution_token + dq early_comma + dq litstring, "!", early_find, entry_to_execution_token, early_comma + dq litstring, "buffer-logical-end", early_find, entry_to_execution_token + dq 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 + + ; Sets all fields in an input buffer metadata structure to zero, + ; effectively detaching and leaking any backing store that had been attached + ; to it. Suitable for use during initialization. + ; + ; In: + ; pointer to input buffer metadata + dq litstring, "zero-input-buffer-metadata", early_create + dq early_docol_codeword + dq litstring, "dup", early_find, entry_to_execution_token, early_comma + dq litstring, "buffer-physical-start", 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, "swap", 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, "buffer-physical-end", 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, "swap", 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, "buffer-logical-start", 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, "swap", 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, "buffer-logical-end", 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, "swap", early_find, entry_to_execution_token, early_comma + dq litstring, "!", early_find, entry_to_execution_token, early_comma + ; Notice the absence of a dup this time. + dq litstring, "input-buffer-refill", 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, "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 early_here, fetch, lit, 8, packalign, early_here_store + + ; Allocates buffer metadata, with no backing store attached. Initializes + ; the metadata to all zeroes. + ; + ; Out: + ; pointer to buffer metadata + dq litstring, "allocate-input-buffer-metadata", early_create + dq early_docol_codeword + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 5*8, early_comma + dq litstring, "allocate", 0, early_find, entry_to_execution_token + dq early_comma + dq litstring, "dup", early_find, entry_to_execution_token, early_comma + dq litstring, "zero-input-buffer-metadata", early_find + dq 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 + + ; Allocates input buffer metadata and a backing store, in one operation. + ; Points the metadata to the backing store. + ; + ; In: + ; buffer capacity in bytes + ; Out: + ; pointer to buffer metadata + dq litstring, "allocate-input-buffer", early_create, early_docol_codeword + dq litstring, "dup", early_find, entry_to_execution_token, early_comma + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 5*8, early_comma + dq litstring, "+", early_find, entry_to_execution_token, early_comma + dq litstring, "allocate", 0, early_find, entry_to_execution_token + dq early_comma + dq litstring, "dup", early_find, entry_to_execution_token, early_comma + dq litstring, "zero-input-buffer-metadata", early_find + dq entry_to_execution_token, early_comma + ; (capacity in bytes, metadata pointer) + dq litstring, "dup", 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, 5*8, early_comma + dq litstring, "+", early_find, entry_to_execution_token, early_comma + ; (capacity in bytes, metadata pointer, metadata pointer, physical start) + dq litstring, "dup", early_find, entry_to_execution_token, early_comma + dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma + dq litstring, "swap", early_find, entry_to_execution_token, early_comma + dq litstring, "buffer-physical-start", early_find, entry_to_execution_token + dq early_comma + dq litstring, "!", early_find, entry_to_execution_token, early_comma + ; (capacity in bytes, metadata pointer, physical start) + dq litstring, "3roll", 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, "dup", early_find, entry_to_execution_token, early_comma + dq litstring, "3unroll", early_find, entry_to_execution_token, early_comma + ; (metadata pointer, physical end, metadata pointer) + dq litstring, "buffer-physical-end", early_find, entry_to_execution_token + dq early_comma + dq litstring, "!", early_find, entry_to_execution_token, early_comma + ; (metadata pointer) + dq litstring, "dup", early_find, entry_to_execution_token, early_comma + dq litstring, "clear-buffer", 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 + + ; Sets the backing store of an input buffer to point at a null-teriminated + ; string and read from it. + ; + ; In: + ; pointer to string + ; pointer to buffer metadata + dq litstring, "attach-string-to-input-buffer", early_create + dq early_docol_codeword + dq litstring, "swap", early_find, entry_to_execution_token, early_comma + ; (string pointer, metadata pointer) + dq litstring, "2dup", early_find, entry_to_execution_token, early_comma + dq litstring, "buffer-physical-start", early_find, entry_to_execution_token + dq early_comma + dq litstring, "!", early_find, entry_to_execution_token, early_comma + ; (string pointer, metadata pointer) + dq litstring, "2dup", early_find, entry_to_execution_token, early_comma + dq litstring, "buffer-logical-start", early_find, entry_to_execution_token + dq early_comma + dq litstring, "!", early_find, entry_to_execution_token, early_comma + ; (string pointer, metadata pointer) + dq litstring, "swap", early_find, entry_to_execution_token, early_comma + dq litstring, "dup", early_find, entry_to_execution_token, early_comma + dq litstring, "stringlen", 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 + ; (string end pointer, metadata pointer) + dq litstring, "2dup", early_find, entry_to_execution_token, early_comma + dq litstring, "buffer-physical-end", early_find, entry_to_execution_token + dq early_comma + dq litstring, "!", early_find, entry_to_execution_token, early_comma + ; (string end pointer, metadata pointer) + dq litstring, "buffer-logical-end", early_find, entry_to_execution_token + dq 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 + + ;;; Initialize our runtime data structures. + ; (heap pointer) + dq litstring, "allocate-input-buffer-metadata", early_find + dq entry_to_execution_token, execute + ; (heap pointer, metadata pointer) + dq swap, litstring, "attach-string-to-input-buffer", early_find + ; (metadata pointer, heap pointer, entry pointer) + dq entry_to_execution_token, swap, unroll3 + ; (heap pointer, metadata pointer, execution token) + dq swap, dup, unroll3 + ; (heap pointer, metadata pointer, execution token, metadata pointer) + dq lit, boot_source, roll3 + ; (heap pointer, metadata pointer, metadata pointer, string pointer, + ; execution token) + dq execute + ; (heap pointer, metadata pointer) + dq swap, litstring, "variable", 0, early_find, entry_to_execution_token + ; (metadata pointer, heap pointer, execution token) + dq swap, unroll3 + ; (heap pointer, metadata pointer, execution token) + dq litstring, "main-input-buffer", swap + ; (heap pointer, metadata pointer, string pointer, execution token) + dq execute + dq litstring, "main-input-buffer", early_find, entry_to_execution_token + dq execute + dq lit, 0, sys_exit ;;; For triage's sake, here's an inventory of everything else in the file. ;;; @@ -8787,6 +9147,28 @@ defword show_source_or_hex_between, 0 dq show_source_between, exit +;;;;;;;;;;;;;; +;;; Lexing ;;; +;;;;;;;;;;;;;; + + +; In: +; next input address +; Out: +; next input address (updated) +; input byte +defword key, 0 + dq docol + dq dup, dup, lit, -8, and, fetch, swap, lit, 7, and + ; (next input address, 64-bit input word, byte index within word) + dq dup, zbranch, 13*8 + dq lit, 1, sub, swap, lit, 256, divmod, swap, drop, swap, branch, -14*8 + dq drop, lit, 0xFF, and + dq swap, lit, 1, add, swap + dq exit + + + ;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Heap bootstrapping ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -9320,6 +9702,13 @@ defword self_raw, 0 dq memcopy dq exit + +defword foo, 0 + dq docol, litstring, "foooooooo", emitstring, exit +defword boot_source, 0 + dq "foo " + dq 0 + ; Routines that traverse the raw code need a way to guess where the end of a ; word's contents are, lest they traverse off the edge of the world and ; segfault. On the heap, we have the "here" pointer to provide an upper bound. -- cgit 1.4.1