diff options
| author | Dmitry Gutov | 2017-09-26 02:49:00 +0300 |
|---|---|---|
| committer | Dmitry Gutov | 2017-09-26 02:52:23 +0300 |
| commit | 827db6b559100153fd7dcab1ecdabd9233e906ab (patch) | |
| tree | 86b823dae67d4adc6ccf1e1723776bd83df72be2 | |
| parent | a2244f417a7cf577172cec927b055f0aca9ef282 (diff) | |
| download | emacs-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.el | 107 |
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 | |||
| 381 | point (where the PPSS is equivalent to nil).") | 381 | point (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). | ||
| 395 | Where LAST is a pair (LAST-POS . LAST-PPS) caching the last invocation | ||
| 396 | and CACHE is a list of (POS . PPSS) pairs, in decreasing POS order. | ||
| 397 | These 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. |
| 428 | The returned value is the same as that of `parse-partial-sexp' | 460 | The 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)) |