Skip to content

Commit

Permalink
Rename READ-AND-CACHE{ -> -TOP-LEVEL-EXPRESSION}, more cosmetic changes
Browse files Browse the repository at this point in the history
  • Loading branch information
scymtym committed Aug 15, 2024
1 parent 55c226c commit e45d10d
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 37 deletions.
2 changes: 1 addition & 1 deletion code/extra-assertions.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
75 changes: 39 additions & 36 deletions code/read.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)))))

0 comments on commit e45d10d

Please sign in to comment.