Garbonzo 2
ci/woodpecker/push/woodpecker Pipeline was successful Details

WIP-incremental-parsing
Hugo Thunnissen 11 months ago
parent 2e6edd70b2
commit f3a5e1d658

@ -83,6 +83,18 @@ linked with."
;; return
parsed))))
;; (cl-defmethod phpinspect-buffer-parse-incrementally ((buffer phpinspect-buffer) &optional edits)
;; (let* ((edits (or edits (phpinspect-edit-tracker-edits
;; (phpinspect-buffer-edit-tracker buffer))))
;; (edit (phpinspect-queue-dequeue edits)))
(cl-defmethod phpinspect-buffer-register-edit
((buffer phpinspect-buffer) (start integer) (end integer) (pre-change-length integer))
(let ((contents (buffer-substring start end)))
(phpinspect-edit-tracker-register
(phpinspect-buffer-edit-tracker buffer) start end pre-change-length contents)))
(cl-defmethod phpinspect-buffer-queue-full-parse ((buffer phpinspect-buffer))
(phpinspect--log "Attempted to queue full parse"))
@ -95,147 +107,6 @@ linked with."
,@body)
(setf (phpinspect-buffer-tree buffer) ,tree-store-sym))))
;; (cl-defmethod phpinspect-buffer-reparse
;; ((buffer phpinspect-buffer) (meta phpinspect-token-meta) (edit phpinspect-edit))
(cl-defmethod phpinspect-buffer-parse-incrementally ((buffer phpinspect-buffer))
(let ((edits
(phpinspect-edit-tracker-edits (phpinspect-buffer-edit-tracker buffer)))
(buffer-tree (phpinspect-buffer-tree buffer)))
(seq-doseq (edit edits)
(let* ((edit-region (phpinspect-edit-region edit))
(edit-delta (phpinspect-edit-delta edit))
(parsed-start)
(parsed-end)
(metas (phpinspect-tree-find-smallest-overlapping-set
buffer-tree edit-region)))
(condition-case err
(dolist (meta metas)
(setq meta (gv-deref meta))
(let ((region (phpinspect-token-metadata-region meta))
(handler-function (symbol-function
(phpinspect-token-metadata-handler meta)))
(temp-tree (phpinspect-make-tree
;; We start parsing at the start of the token
:start (phpinspect-region-start region)
;; We expect to end parsing at the end of the
;; edit region, but this could not be the case
;; as some handlers ignore point-max.
:end (point-max)
:value 'temp-tree-root))
(parsed)
(parsed-tree))
(phpinspect-buffer-with-tree buffer temp-tree
(with-current-buffer (phpinspect-buffer-buffer buffer)
(save-excursion
(goto-char (phpinspect-region-start region))
(unless (looking-at
(phpinspect-handler-regexp
(phpinspect-token-metadata-handler meta)))
;; The token type changed, reparsing the parent is
;; required to determine its new nature.
(throw 'recurse-parent))
(setq parsed
(funcall handler-function (match-string 0)
(phpinspect-region-end edit-region)))
(phpinspect-set-token-metadata-when-current-buffer
parsed (phpinspect-region-start region) (point)
(phpinspect-token-metadata-handler meta)))))
(setq parsed-tree
(phpinspect-tree-detach
(seq-elt (phpinspect-tree-children temp-tree) 0)))
(cond ((> (phpinspect-tree-end parsed-tree)
(+ (phpinspect-region-end region) edit-delta))
;; Changes in edit region changed meaning of tokens
;; outside of it.
(throw 'recurse-parent))
((< (phpinspect-tree-end parsed-tree)
(+ (phpinspect-region-end region) edit-delta))
;; No edits after, but token did not grow to expected
;; size.
(unless (phpinspect-edit-tracker-edit-after edit)
(throw 'recurse-parent)))
((
-
;; (with-current-buffer (phpinspect-buffer-buffer buffer)
;; (let ((edits
;; (phpinspect-edit-tracker-edits (phpinspect-buffer-edit-tracker buffer)))
;; (buffer-tree (phpinspect-buffer-tree buffer)))
;; (unwind-protect
;; (progn
;; (seq-doseq (edit edits)
;; (let* ((edit-region (phpinspect-edit-region edit))
;; (metas (phpinspect-tree-find-smallest-overlapping-set
;; buffer-tree edit-region)))
;; (condition-case err
;; (dolist (meta metas)
;; (setq meta (gv-deref meta))
;; (let ((region (phpinspect-token-metadata-region meta))
;; (handler-function (symbol-function
;; (phpinspect-token-metadata-handler meta)))
;; (temp-tree (phpinspect-make-tree
;; ;; We start parsing at the start of the token
;; :start (phpinspect-region-start region)
;; ;; We expect to end parsing at the end of the edit region
;; :end (phpinspect-region-end edit-region)
;; :value 'temp-tree-root))
;; (parse-result)
;; (parse-result-tree))
;; (save-excursion
;; (goto-char (phpinspect-region-start region))
;; ;; Override buffer tree
;; (setf (phpinspect-buffer-tree buffer) temp-tree)
;; (setq parse-result (funcall handler-function))
;; (phpinspect-set-token-metadata-when-current-buffer
;; parse-result (phpinspect-region-start region) (point)
;; (phpinspect-token-metadata-handler meta))
;; (if (eq (phpinspect-tree-value temp-tree) 'temp-tree-root)
;; (setq parse-result-tree
;; (phpinspect-tree-detach
;; (seq-elt (phpinspect-tree-children temp-tree) 0)))
;; ;; New token width exceeds edit region.
;; (phpinspect-buffer-queue-full-parse buffer)
;; (throw 'break))
;; New token region encloses editen region, stop parsing.
;; (let* ((new-meta (gv-deref (phpinspect-tree-value parse-result-tree)))
;; (new-token (phpinspect-token-metadata-token new-meta)))
;; (if (and (phpinspect-incomplete-token-p new-token)
;; (phpinspect-edit-tracker-edit-after
;; (phpinspect-buffer-edit-tracker buffer) edit))
;; ;; The token is incomplete, and there are edits after this token
;; (when (phpinspect-region-encloses new-meta edit-region)
;; (throw 'break))))))
;; (break)))))
;; ;; Restore buffer tree
;; (setf (phpinspect-buffer-tree buffer) buffer-tree)))))
;; (if (< 1 (length metas))
;; (setq reparse-meta (phpinspect-tree-value
;; (phpinspect-tree-parent
;; (phpinspect-token-metadata-tree (car metas)))))
;; (setq reparse-meta (car metas)))
;; (if reparse-meta
;; (phpinspect-buffer-reparse buffer reparse-meta edit)
;; ;; Nothing found to reparse.. Just reparse entire buffer to be sure
;; (phpinspect--log "[WARNING] phpinspect-buffer-parse-incrementally: No reparsable tokens found, reparsing entire buffer.")
;; (phpinspect-buffer-parse buffer))))))
(cl-defmethod phpinspect-buffer-set-token-metadata
((buffer phpinspect-buffer) token (metadata phpinspect-token-metadata))
"Set the METADATA associated with TOKEN that was parsed in BUFFER"
@ -255,7 +126,6 @@ linked with."
metadata)))
(setf (phpinspect-token-metadata-tree metadata) tree-node))))))
(cl-defmethod phpinspect-buffer-get-token-metadata ((buffer phpinspect-buffer) token)
(let ((ref (gethash token (phpinspect-buffer-metadata-map buffer))))
(when ref (gv-deref ref))))
@ -268,9 +138,12 @@ linked with."
(phpinspect-tree-traverse-overlappig (phpinspect-buffer-tree buffer) point)))
(cl-defstruct (phpinspect-edit-tracker (:constructor phpinspect-make-edit-tracker))
(edits (phpinspect-make-ll)))
(edits (phpinspect-make-queue)))
(cl-defstruct (phpinspect-edit (:constructor phpinspect-make-edit))
(contents ""
:type string
:documentation "The contents of the edit")
(region nil
:type phpinspect-region
:documentation
@ -280,98 +153,14 @@ linked with."
:documentation
"The change in width of the edit region"))
(cl-defmethod phpinspect-edit-concat ((edit1 phpinspect-edit) (edit2 phpinspect-edit))
"Absorb EDIT2 into EDIT1. Returns EDIT1."
(let ((min) (max) (delta)
(region1 (phpinspect-edit-region edit1))
(region2 (phpinspect-edit-region edit2)))
(if (< (phpinspect-region-start region1)
(phpinspect-region-start region2))
(setq min (phpinspect-region-start region1))
(setq min (phpinspect-region-start region2)))
(if (> (phpinspect-region-end region1)
(phpinspect-region-end region2))
(setq max (phpinspect-region-end region1))
(setq max (phpinspect-region-end region2)))
(setq delta (+ (phpinspect-edit-delta edit1)
(phpinspect-edit-delta edit2)))
(setf (phpinspect-edit-delta edit1) delta)
(setf (phpinspect-edit-region edit1) (phpinspect-make-region min max))
edit1))
(cl-defmethod phpinspect-edit-overlaps ((edit1 phpinspect-edit) (edit2 phpinspect-edit))
(phpinspect-region-overlaps (phpinspect-edit-region edit1)
(phpinspect-edit-region edit2)))
(cl-defmethod phpinspect-edit-could-overlap ((edit1 phpinspect-edit) (edit2 phpinspect-edit))
(> (phpinspect-region-end (phpinspect-edit-region edit1))
(phpinspect-region-start (phpinspect-edit-region edit2))))
(cl-defmethod phpinspect-edit-tracker-mark
((tracker phpinspect-edit-tracker) (start integer) (end integer) (pre-change-length integer))
(let* ((edits (phpinspect-edit-tracker-edits tracker))
(edit (phpinspect-make-edit :region (phpinspect-make-region start end)
:delta (- (- end start) pre-change-length)))
(first-in-range (seq-find (lambda (e) (phpinspect-edit-could-overlap edit e))
edits))
(insertion-link)
(first-overlapper)
(overlappers))
(when first-in-range
(if (phpinspect-edit-overlaps edit first-in-range)
(progn
;; If this is the first overlapper, we should insert before it.
(setq insertion-link (phpinspect-llnode-left
(phpinspect-ll-link edits first-in-range)))
(setq first-overlapper first-in-range))
;; If this is not an overlapper, we should insert after it, as the
;; entire region spans a range before the edit.
(setq insertion-link (phpinspect-ll-link edits first-in-range))))
(unless first-overlapper
(setq first-overlapper (seq-find (lambda (e) (phpinspect-edit-overlaps edit e))
(or insertion-link
(phpinspect-ll-link edits first-in-range)))))
(when first-overlapper
(setq overlappers
(seq-take-while (lambda (e) (phpinspect-edit-overlaps e edit))
(phpinspect-ll-link edits first-overlapper)))
;; Break overlappers away from edit list, as they're about to be replaced.
(setq overlappers (phpinspect-slice-detach overlappers)))
;; Absorb all overlapping edits into our newly created edit
(seq-doseq (overlap overlappers)
(phpinspect-edit-concat edit overlap))
(if insertion-link
(phpinspect-ll-insert-right insertion-link edit)
(phpinspect-ll-push edit edits))))
(cl-defmethod phpinspect-edit-tracker-unmark
((tracker phpinspect-edit-tracker) (start integer) (end integer))
(let* ((region (phpinspect-make-region start end))
(edits (phpinspect-edit-tracker-edits tracker))
(first-enclosing
(seq-find (lambda (e) (phpinspect-region-encloses
region (phpinspect-edit-region e)))
edits)))
(when first-enclosing
(phpinspect-slice-detach
(seq-take-while (lambda (e) (phpinspect-region-encloses
region (phpinspect-edit-region e)))
edits)))))
(cl-defmethod phpinspect-edit-tracker-register
((tracker phpinspect-edit-tracker) (start integer) (end integer)
(pre-change-length integer) (contents string))
(phpinspect-queue-enqueue
(phpinspect-edit-tracker-edits tracker)
(phpinspect-make-edit :region (phpinspect-make-region start end)
:delta (- (- end start) pre-change-length)
:contents contents)))
(cl-defmethod phpinspect-edit-tracker-edit-after
((tracker phpinspect-edit-tracker) (edit phpinspect-edit))
(phpinspect-llnode-value
(phpinspect-llnode-right
(phpinspect-ll-link
(phpinspect-edit-tracker-edits tracker) edit))))
(provide 'phpinspect-buffer)

@ -83,7 +83,7 @@
(funcall (phpinspect-queue-item-subscription item))))
(cl-defmethod phpinspect-queue-dequeue ((item phpinspect-queue-item))
"Remove the thing at the front of the queue that ITEM is part of an return it."
"Remove the thing at the front of the queue that ITEM is part of and return it."
(let* ((first (phpinspect-queue-first item))
(thing (phpinspect-queue-item-thing first))
(next (phpinspect-queue-item-next first)))

Loading…
Cancel
Save