aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Gutov2017-09-26 02:49:00 +0300
committerDmitry Gutov2017-09-26 02:52:23 +0300
commit827db6b559100153fd7dcab1ecdabd9233e906ab (patch)
tree86b823dae67d4adc6ccf1e1723776bd83df72be2
parenta2244f417a7cf577172cec927b055f0aca9ef282 (diff)
downloademacs-827db6b559100153fd7dcab1ecdabd9233e906ab.tar.gz
emacs-827db6b559100153fd7dcab1ecdabd9233e906ab.zip
Use a separate syntax-ppss cache for narrowed buffers
* lisp/emacs-lisp/syntax.el (syntax-ppss-wide): New variable, to contain the data from `syntax-ppss-last' and `syntax-ppss-cache'. (syntax-ppss-cache, syntax-ppss-last): Remove. (syntax-ppss-narrow, syntax-ppss-narrow-start): New variables. (syntax-ppss-flush-cache): Flush both caches. (syntax-ppss--data): Return the appropriate last result and buffer cache for the current restriction. (syntax-ppss, syntax-ppss-debug): Use it (bug#22983).
-rw-r--r--lisp/emacs-lisp/syntax.el107
1 files changed, 72 insertions, 35 deletions
diff --git a/lisp/emacs-lisp/syntax.el b/lisp/emacs-lisp/syntax.el
index f6137837858..9eb6bde7454 100644
--- a/lisp/emacs-lisp/syntax.el
+++ b/lisp/emacs-lisp/syntax.el
@@ -381,10 +381,26 @@ This function should move the cursor back to some syntactically safe
381point (where the PPSS is equivalent to nil).") 381point (where the PPSS is equivalent to nil).")
382(make-obsolete-variable 'syntax-begin-function nil "25.1") 382(make-obsolete-variable 'syntax-begin-function nil "25.1")
383 383
384(defvar-local syntax-ppss-cache nil 384;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
385 "List of (POS . PPSS) pairs, in decreasing POS order.") 385;; Several caches.
386(defvar-local syntax-ppss-last nil 386;;
387 "Cache of (LAST-POS . LAST-PPSS).") 387;; Because `syntax-ppss' is equivalent to (parse-partial-sexp
388;; (POINT-MIN) x), we need either to empty the cache when we narrow
389;; the buffer, which is suboptimal, or we need to use several caches.
390;; We use two of them, one for widened buffer, and one for narrowing.
391;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
392
393(defvar-local syntax-ppss-wide nil
394 "Cons of two elements (LAST . CACHE).
395Where LAST is a pair (LAST-POS . LAST-PPS) caching the last invocation
396and CACHE is a list of (POS . PPSS) pairs, in decreasing POS order.
397These are valid when the buffer has no restriction.")
398
399(defvar-local syntax-ppss-narrow nil
400 "Same as `syntax-ppss-wide' but for a narrowed buffer.")
401
402(defvar-local syntax-ppss-narrow-start nil
403 "Start position of the narrowing for `syntax-ppss-narrow'.")
388 404
389(defalias 'syntax-ppss-after-change-function 'syntax-ppss-flush-cache) 405(defalias 'syntax-ppss-after-change-function 'syntax-ppss-flush-cache)
390(defun syntax-ppss-flush-cache (beg &rest ignored) 406(defun syntax-ppss-flush-cache (beg &rest ignored)
@@ -392,24 +408,29 @@ point (where the PPSS is equivalent to nil).")
392 ;; Set syntax-propertize to refontify anything past beg. 408 ;; Set syntax-propertize to refontify anything past beg.
393 (setq syntax-propertize--done (min beg syntax-propertize--done)) 409 (setq syntax-propertize--done (min beg syntax-propertize--done))
394 ;; Flush invalid cache entries. 410 ;; Flush invalid cache entries.
395 (while (and syntax-ppss-cache (> (caar syntax-ppss-cache) beg)) 411 (dolist (cell (list syntax-ppss-wide syntax-ppss-narrow))
396 (setq syntax-ppss-cache (cdr syntax-ppss-cache))) 412 (pcase cell
397 ;; Throw away `last' value if made invalid. 413 (`(,last . ,cache)
398 (when (< beg (or (car syntax-ppss-last) 0)) 414 (while (and cache (> (caar cache) beg))
399 ;; If syntax-begin-function jumped to BEG, then the old state at BEG can 415 (setq cache (cdr cache)))
400 ;; depend on the text after BEG (which is presumably changed). So if 416 ;; Throw away `last' value if made invalid.
401 ;; BEG=(car (nth 10 syntax-ppss-last)) don't reuse that data because the 417 (when (< beg (or (car last) 0))
402 ;; assumed nil state at BEG may not be valid any more. 418 ;; If syntax-begin-function jumped to BEG, then the old state at BEG can
403 (if (<= beg (or (syntax-ppss-toplevel-pos (cdr syntax-ppss-last)) 419 ;; depend on the text after BEG (which is presumably changed). So if
404 (nth 3 syntax-ppss-last) 420 ;; BEG=(car (nth 10 syntax-ppss-last)) don't reuse that data because the
405 0)) 421 ;; assumed nil state at BEG may not be valid any more.
406 (setq syntax-ppss-last nil) 422 (if (<= beg (or (syntax-ppss-toplevel-pos (cdr last))
407 (setcar syntax-ppss-last nil))) 423 (nth 3 last)
408 ;; Unregister if there's no cache left. Sadly this doesn't work 424 0))
409 ;; because `before-change-functions' is temporarily bound to nil here. 425 (setq last nil)
410 ;; (unless syntax-ppss-cache 426 (setcar last nil)))
411 ;; (remove-hook 'before-change-functions 'syntax-ppss-flush-cache t)) 427 ;; Unregister if there's no cache left. Sadly this doesn't work
412 ) 428 ;; because `before-change-functions' is temporarily bound to nil here.
429 ;; (unless cache
430 ;; (remove-hook 'before-change-functions 'syntax-ppss-flush-cache t))
431 (setcar cell last)
432 (setcdr cell cache)))
433 ))
413 434
414(defvar syntax-ppss-stats 435(defvar syntax-ppss-stats
415 [(0 . 0.0) (0 . 0.0) (0 . 0.0) (0 . 0.0) (0 . 0.0) (1 . 2500.0)]) 436 [(0 . 0.0) (0 . 0.0) (0 . 0.0) (0 . 0.0) (0 . 0.0) (1 . 2500.0)])
@@ -423,6 +444,17 @@ point (where the PPSS is equivalent to nil).")
423(defvar-local syntax-ppss-table nil 444(defvar-local syntax-ppss-table nil
424 "Syntax-table to use during `syntax-ppss', if any.") 445 "Syntax-table to use during `syntax-ppss', if any.")
425 446
447(defun syntax-ppss--data ()
448 (if (eq (point-min) 1)
449 (progn
450 (unless syntax-ppss-wide
451 (setq syntax-ppss-wide (cons nil nil)))
452 syntax-ppss-wide)
453 (unless (eq syntax-ppss-narrow-start (point-min))
454 (setq syntax-ppss-narrow-start (point-min))
455 (setq syntax-ppss-narrow (cons nil nil)))
456 syntax-ppss-narrow))
457
426(defun syntax-ppss (&optional pos) 458(defun syntax-ppss (&optional pos)
427 "Parse-Partial-Sexp State at POS, defaulting to point. 459 "Parse-Partial-Sexp State at POS, defaulting to point.
428The returned value is the same as that of `parse-partial-sexp' 460The returned value is the same as that of `parse-partial-sexp'
@@ -439,10 +471,13 @@ running the hook."
439 (syntax-propertize pos) 471 (syntax-propertize pos)
440 ;; 472 ;;
441 (with-syntax-table (or syntax-ppss-table (syntax-table)) 473 (with-syntax-table (or syntax-ppss-table (syntax-table))
442 (let ((old-ppss (cdr syntax-ppss-last)) 474 (let* ((cell (syntax-ppss--data))
443 (old-pos (car syntax-ppss-last)) 475 (ppss-last (car cell))
444 (ppss nil) 476 (ppss-cache (cdr cell))
445 (pt-min (point-min))) 477 (old-ppss (cdr ppss-last))
478 (old-pos (car ppss-last))
479 (ppss nil)
480 (pt-min (point-min)))
446 (if (and old-pos (> old-pos pos)) (setq old-pos nil)) 481 (if (and old-pos (> old-pos pos)) (setq old-pos nil))
447 ;; Use the OLD-POS if usable and close. Don't update the `last' cache. 482 ;; Use the OLD-POS if usable and close. Don't update the `last' cache.
448 (condition-case nil 483 (condition-case nil
@@ -475,7 +510,7 @@ running the hook."
475 ;; The OLD-* data can't be used. Consult the cache. 510 ;; The OLD-* data can't be used. Consult the cache.
476 (t 511 (t
477 (let ((cache-pred nil) 512 (let ((cache-pred nil)
478 (cache syntax-ppss-cache) 513 (cache ppss-cache)
479 (pt-min (point-min)) 514 (pt-min (point-min))
480 ;; I differentiate between PT-MIN and PT-BEST because 515 ;; I differentiate between PT-MIN and PT-BEST because
481 ;; I feel like it might be important to ensure that the 516 ;; I feel like it might be important to ensure that the
@@ -491,7 +526,7 @@ running the hook."
491 (if cache (setq pt-min (caar cache) ppss (cdar cache))) 526 (if cache (setq pt-min (caar cache) ppss (cdar cache)))
492 527
493 ;; Setup the before-change function if necessary. 528 ;; Setup the before-change function if necessary.
494 (unless (or syntax-ppss-cache syntax-ppss-last) 529 (unless (or ppss-cache ppss-last)
495 (add-hook 'before-change-functions 530 (add-hook 'before-change-functions
496 'syntax-ppss-flush-cache t t)) 531 'syntax-ppss-flush-cache t t))
497 532
@@ -541,7 +576,7 @@ running the hook."
541 pt-min (setq pt-min (/ (+ pt-min pos) 2)) 576 pt-min (setq pt-min (/ (+ pt-min pos) 2))
542 nil nil ppss)) 577 nil nil ppss))
543 (push (cons pt-min ppss) 578 (push (cons pt-min ppss)
544 (if cache-pred (cdr cache-pred) syntax-ppss-cache))) 579 (if cache-pred (cdr cache-pred) ppss-cache)))
545 580
546 ;; Compute the actual return value. 581 ;; Compute the actual return value.
547 (setq ppss (parse-partial-sexp pt-min pos nil nil ppss)) 582 (setq ppss (parse-partial-sexp pt-min pos nil nil ppss))
@@ -562,13 +597,15 @@ running the hook."
562 (if (> (- (caar cache-pred) pos) syntax-ppss-max-span) 597 (if (> (- (caar cache-pred) pos) syntax-ppss-max-span)
563 (push pair (cdr cache-pred)) 598 (push pair (cdr cache-pred))
564 (setcar cache-pred pair)) 599 (setcar cache-pred pair))
565 (if (or (null syntax-ppss-cache) 600 (if (or (null ppss-cache)
566 (> (- (caar syntax-ppss-cache) pos) 601 (> (- (caar ppss-cache) pos)
567 syntax-ppss-max-span)) 602 syntax-ppss-max-span))
568 (push pair syntax-ppss-cache) 603 (push pair ppss-cache)
569 (setcar syntax-ppss-cache pair))))))))) 604 (setcar ppss-cache pair)))))))))
570 605
571 (setq syntax-ppss-last (cons pos ppss)) 606 (setq ppss-last (cons pos ppss))
607 (setcar cell ppss-last)
608 (setcdr cell ppss-cache)
572 ppss) 609 ppss)
573 (args-out-of-range 610 (args-out-of-range
574 ;; If the buffer is more narrowed than when we built the cache, 611 ;; If the buffer is more narrowed than when we built the cache,
@@ -582,7 +619,7 @@ running the hook."
582(defun syntax-ppss-debug () 619(defun syntax-ppss-debug ()
583 (let ((pt nil) 620 (let ((pt nil)
584 (min-diffs nil)) 621 (min-diffs nil))
585 (dolist (x (append syntax-ppss-cache (list (cons (point-min) nil)))) 622 (dolist (x (append (cdr (syntax-ppss--data)) (list (cons (point-min) nil))))
586 (when pt (push (- pt (car x)) min-diffs)) 623 (when pt (push (- pt (car x)) min-diffs))
587 (setq pt (car x))) 624 (setq pt (car x)))
588 min-diffs)) 625 min-diffs))