From e45d10d38a02b4789ee4fb7c2ddb2c437a5cd7e0 Mon Sep 17 00:00:00 2001 From: Jan Moringen Date: Thu, 1 Aug 2024 07:22:28 +0200 Subject: [PATCH] Rename READ-AND-CACHE{ -> -TOP-LEVEL-EXPRESSION}, more cosmetic changes --- code/extra-assertions.lisp | 2 +- code/read.lisp | 75 ++++++++++++++++++++------------------ 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/code/extra-assertions.lisp b/code/extra-assertions.lisp index c99bcd8..e694771 100644 --- a/code/extra-assertions.lisp +++ b/code/extra-assertions.lisp @@ -245,7 +245,7 @@ (unless (null result) (check-absolute-wad-with-relative-descendants result)))) -(dbg:define-invariant read-and-cache +(dbg:define-invariant read-and-cache-top-level-expression :after (((result 1)) (unless (null result) (assert (typep result 'wad)) diff --git a/code/read.lisp b/code/read.lisp index c178b28..8b8dbf0 100644 --- a/code/read.lisp +++ b/code/read.lisp @@ -11,8 +11,8 @@ :end-column end-column :condition condition))) -;;; PARSE-AND-CACHE collects Eclector errors in *ERRORS* during -;;; parsing. +;;; The `read-maybe-nothing' method collects Eclector errors in +;;; *ERRORS* during reading. (defvar *errors*) ;;; Establish a handler which collects `reader-error's into `*errors*' and @@ -65,68 +65,71 @@ (push cached (first eclector.parse-result::*stack*)) ; HACK (advance-stream-to-beyond-wad stream cached))))) -(defun read-and-cache (analyzer client) - ;; Use ECLECTOR.READER:READ-MAYBE-NOTHING to read either a single +(defun read-and-cache-top-level-expression (analyzer client) + ;; Use `eclector.reader:read-maybe-nothing' to read either a single ;; skipped input or an object. Both are pushed into the prefix of ;; the cache that is associated with ANALYZER. ;; - ;; For any errors during parsing, WITH-ERROR-RECORDING creates an - ;; ERROR-WAD records it in *ERRORS*, then asks Eclector to perform - ;; the appropriate recovery. The READ-MAYBE-NOTHING method takes - ;; care of integrating the collected ERROR-WADs into the wad tree. + ;; For any errors during parsing, `with-error-recording' creates an + ;; `error-wad', records it in `*errors*' and then asks Eclector to + ;; perform the appropriate recovery. The `read-maybe-nothing' + ;; method takes care of integrating the collected `error-wad's into + ;; the wad tree. (multiple-value-bind (object kind wad) (with-error-recording () (eclector.reader:read-maybe-nothing client analyzer nil nil)) (declare (ignore object)) (case kind - (:eof) ; nothing to do for end of input - (:whitespace) ; nothing to do for whitespace - (t ; got a top-level, absolute wads + (:eof) ; nothing to do for end of input + (:whitespace) ; nothing to do for whitespace + (t ; got a top-level, absolute wad (if (null wad) ; or possibly nothing, but only if KIND is `:skip' (assert (eq kind :skip)) (push-to-prefix (cache analyzer) wad)))) (values kind wad))) (defun read-forms (analyzer) - (let ((cache (cache analyzer))) + (let* ((cache (cache analyzer)) + (prefix (prefix cache))) ;; Position ANALYZER (which is a stream) after the last prefix wad ;; (remember the cache prefix is stored in reverse order) if any. (update-lines-cache analyzer (lines analyzer)) - (let ((prefix (prefix cache))) - (setf (values (line-number analyzer) (item-number analyzer)) - (if (null prefix) - (values 0 0) - (let ((first (first prefix))) - (values (end-line first) (end-column first)))))) + (setf (values (line-number analyzer) (item-number analyzer)) + (if (null prefix) + (values 0 0) + (let ((first (first prefix))) + (values (end-line first) (end-column first))))) ;; Keep reading top-level expressions until the stream position is ;; at the start of the cache suffix (wads on the cache suffix are ;; unmodified and relative except the first one, so neither - ;; re-READing nor adjusting them is necessary) or the EOF is + ;; re-`read'ing nor adjusting them is necessary) or the EOF is ;; reached. Remove wads from the cache residue and cache suffix ;; as the stream positions passes them by. Push newly created - ;; wads to the cache prefix (this happens in `parse-and-cache'). - (loop with client = (make-instance 'client :stream* analyzer) - with *cache* = cache - for kind = (eclector.reader:call-as-top-level-read - client (lambda () - (read-and-cache analyzer client)) - analyzer t nil nil) + ;; wads to the cache prefix (this happens in + ;; `read-and-cache-top-level-expression'). + (loop :with client = (make-instance 'client :stream* analyzer) + :with *cache* = cache + :for kind = (eclector.reader:call-as-top-level-read + client (lambda () + (read-and-cache-top-level-expression + analyzer client)) + analyzer t nil nil) ;; If we reach EOF while reading whitespace, the cache ;; suffix must be empty, and the cache residue is either ;; empty or it contains wads that should be removed. If we ;; do not reach EOF, then we stop only if the current ;; position is that of the first parse result on the cache ;; suffix. - when (or (eq kind :eof) - (let ((suffix (suffix cache))) - (and (not (null suffix)) - (position= (first suffix) analyzer)))) - do (setf (residue cache) '()) - (return-from read-forms nil) + :when (or (eq kind :eof) + (let ((suffix (suffix cache))) + (and (not (null suffix)) + (position= (first suffix) analyzer)))) + :do (setf (residue cache) '()) + (return-from read-forms nil) ;; In case we skipped some whitespace, discard any wads on ;; the cache residue and cache suffix that are now before ;; the current stream position. - unless (eq kind :whitespace) - do (drain-result-list analyzer cache residue pop-from-residue) - (when (null (residue cache)) - (drain-result-list analyzer cache suffix pop-from-suffix))))) + :unless (eq kind :whitespace) + :do (drain-result-list analyzer cache residue pop-from-residue) + (when (null (residue cache)) + (drain-result-list analyzer cache suffix pop-from-suffix)))))