emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/phpinspect 0596bc52bf 091/126: Optimize splay tree and


From: ELPA Syncer
Subject: [elpa] externals/phpinspect 0596bc52bf 091/126: Optimize splay tree and use it to store token's children
Date: Sat, 12 Aug 2023 00:58:47 -0400 (EDT)

branch: externals/phpinspect
commit 0596bc52bf91104d7520a7d99991da0633369790
Author: Hugo Thunnissen <devel@hugot.nl>
Commit: Hugo Thunnissen <devel@hugot.nl>

    Optimize splay tree and use it to store token's children
---
 benchmarks/parse-file.el     |   2 +-
 benchmarks/splay-tree.el     |  33 +++
 phpinspect-bmap.el           | 181 ++++-----------
 phpinspect-eldoc.el          |  44 ++--
 phpinspect-meta.el           | 130 +++++++++++
 phpinspect-resolvecontext.el |  38 ++--
 phpinspect-splayt.el         | 517 ++++++++++++++++++++++++++-----------------
 test/test-bmap.el            |   3 +
 test/test-splayt.el          |  78 +++++--
 9 files changed, 623 insertions(+), 403 deletions(-)

diff --git a/benchmarks/parse-file.el b/benchmarks/parse-file.el
index c2f05b2b25..604ba2e833 100644
--- a/benchmarks/parse-file.el
+++ b/benchmarks/parse-file.el
@@ -62,7 +62,7 @@
 
         (garbage-collect)
 
-        ;;(profiler-start 'cpu+mem)
+        ;;(profiler-start 'cpu)
         (message "Incremental parse after 2 more edits:")
         (phpinspect-with-parse-context (phpinspect-make-pctx :incremental t 
:previous-bmap bmap-after :edtrack edtrack)
           (benchmark 1 '(phpinspect-parse-current-buffer)))
diff --git a/benchmarks/splay-tree.el b/benchmarks/splay-tree.el
new file mode 100644
index 0000000000..261ddfe08a
--- /dev/null
+++ b/benchmarks/splay-tree.el
@@ -0,0 +1,33 @@
+
+
+(require 'phpinspect-splayt)
+
+(let ((here (file-name-directory (or load-file-name buffer-file-name)))
+      (tree (phpinspect-make-splayt)))
+  (message "Splay tree 10000 insertions:")
+  (garbage-collect)
+  (benchmark
+   1 '(dotimes (i 10000)
+        (phpinspect-splayt-insert tree i 'value)))
+
+  (message "Splay tree 10000 lookups:")
+  (garbage-collect)
+  (benchmark
+   1 '(dotimes (i 10000)
+        (phpinspect-splayt-find tree i))))
+
+
+(let (map)
+  (message "Hashtable 10000 insertions:")
+  (garbage-collect)
+  (benchmark
+   1 '(progn
+        (setq map (make-hash-table :test #'eq :size 10000 :rehash-size 1.5))
+        (dotimes (i 10000)
+        (puthash i 'value map))))
+
+  (message "Hashtable 10000 lookups:")
+  (garbage-collect)
+  (benchmark
+   1 '(dotimes (i 10000)
+        (gethash i map))))
diff --git a/phpinspect-bmap.el b/phpinspect-bmap.el
index 3519ac66a7..2b0221128f 100644
--- a/phpinspect-bmap.el
+++ b/phpinspect-bmap.el
@@ -24,6 +24,7 @@
 ;;; Code:
 
 (require 'phpinspect-splayt)
+(require 'phpinspect-meta)
 
 (cl-defstruct (phpinspect-bmap (:constructor phpinspect-make-bmap))
   (starts (make-hash-table :test #'eql
@@ -71,77 +72,26 @@
   (and (<= (phpinspect-region-start reg1) (phpinspect-region-start reg2))
        (>= (phpinspect-region-end reg1) (phpinspect-region-end reg2))))
 
-(defsubst phpinspect-make-meta (parent start end whitespace-before token 
&optional overlay right-siblings)
-  (list 'meta parent start end whitespace-before token overlay right-siblings))
+(define-inline phpinspect-overlay-bmap (overlay)
+  (inline-quote (car (nthcdr 4 ,overlay))))
 
-(defsubst phpinspect-meta-parent (meta)
-  (cadr meta))
+(define-inline phpinspect-overlay-delta (overlay)
+  (inline-quote (cadddr ,overlay)))
 
-(gv-define-setter phpinspect-meta-end (end meta) `(setcar (cdddr ,meta) ,end))
-(gv-define-setter phpinspect-meta-start (start meta) `(setcar (cddr ,meta) 
,start))
-(gv-define-setter phpinspect-meta-overlay (overlay meta) `(setcar (nthcdr 6 
,meta) ,overlay))
-(gv-define-setter phpinspect-meta-parent (parent meta) `(setcar (cdr ,meta) 
,parent))
-(gv-define-setter phpinspect-meta-right-siblings (siblings meta) `(setcar 
(nthcdr 7 ,meta) ,siblings))
+(define-inline phpinspect-overlay-start (overlay)
+  (inline-quote (cadr ,overlay)))
 
-(defsubst phpinspect-meta-right-siblings (meta)
-  (car (nthcdr 7 meta)))
+(define-inline phpinspect-overlay-end (overlay)
+  (inline-quote (caddr ,overlay)))
 
-(defsubst phpinspect-meta-overlay (meta)
-  (car (nthcdr 6 meta)))
+(define-inline phpinspect-overlay-token-meta (overlay)
+  (inline-quote (car (nthcdr 5 ,overlay))))
 
-(defsubst phpinspect-meta-token (meta)
-  (car (nthcdr 5 meta)))
-
-(defsubst phpinspect-meta-end (meta)
-  (cadddr meta))
-
-(defsubst phpinspect-meta-whitespace-before (meta)
-  (car (cddddr meta)))
-
-(defsubst phpinspect-meta-width (meta)
-  (- (phpinspect-meta-end meta) (phpinspect-meta-start meta)))
-
-(defun phpinspect-meta-sort-width (meta1 meta2)
-  (< (phpinspect-meta-width meta1) (phpinspect-meta-width meta2)))
-
-(defsubst phpinspect-meta-start (meta)
-  (caddr meta))
-
-(defsubst phpinspect-meta-overlaps-point (meta point)
-  (and (> (phpinspect-meta-end meta) point)
-       (<= (phpinspect-meta-start meta) point)))
-
-(defsubst phpinspect-meta-find-parent-matching-token (meta predicate)
-  (if (funcall predicate (phpinspect-meta-token meta))
-      meta
-    (catch 'found
-      (while (phpinspect-meta-parent meta)
-        (setq meta (phpinspect-meta-parent meta))
-        (when (funcall predicate (phpinspect-meta-token meta))
-          (throw 'found meta))))))
-
-(gv-define-setter phpinspect-overlay-end (end overlay) `(setcar (cddr 
,overlay) ,end))
-(gv-define-setter phpinspect-overlay-start (start overlay) `(setcar (cdr 
,overlay) ,start))
-(gv-define-setter phpinspect-overlay-delta (delta overlay) `(setcar (cdddr 
,overlay) ,delta))
-
-(defsubst phpinspect-overlay-bmap (overlay)
-  (car (nthcdr 4 overlay)))
-
-(defsubst phpinspect-overlay-delta (overlay)
-  (cadddr overlay))
-
-(defsubst phpinspect-overlay-start (overlay)
-  (cadr overlay))
-
-(defsubst phpinspect-overlay-end (overlay)
-  (caddr overlay))
-
-(defsubst phpinspect-overlay-token-meta (overlay)
-  (car (nthcdr 5 overlay)))
-
-(defsubst phpinspect-overlay-overlaps-point (overlay point)
-  (and (> (phpinspect-overlay-end overlay) point)
-       (<= (phpinspect-overlay-start overlay) point)))
+(define-inline phpinspect-overlay-overlaps-point (overlay point)
+  (inline-letevals (overlay point)
+    (inline-quote
+     (and (> (phpinspect-overlay-end ,overlay) ,point)
+          (<= (phpinspect-overlay-start ,overlay) ,point)))))
 
 (defmacro phpinspect-bmap-iterate-region (region place-and-bmap &rest body)
   (declare (indent defun))
@@ -170,27 +120,13 @@
         (_ignored (gensym))
         (overlay-start (gensym))
         (overlay-end (gensym)))
-    `(let ((,bmap-stack (list ,(cadr place-and-bmap)))
-           (,bmap))
-       (while (setq ,bmap (pop ,bmap-stack))
-         (if (phpinspect-overlay-p ,bmap)
-             (let ((,overlay-start (phpinspect-overlay-start ,bmap))
-                   (,overlay-end (phpinspect-overlay-end ,bmap)))
-               (maphash (lambda (,_ignored ,place)
-                          (setq ,place (phpinspect-overlay-wrap-meta ,bmap 
,place))
-                          (when (and (<= ,overlay-start
-                                         (phpinspect-meta-start ,place))
-                                     (>= ,overlay-end
-                                         (phpinspect-meta-end ,place)))
-                            (if (phpinspect-meta-overlay ,place)
-                              (push (phpinspect-meta-overlay ,place) 
,bmap-stack)
-                              ,@body)))
-                        (phpinspect-bmap-meta (phpinspect-overlay-bmap 
,bmap))))
-           (maphash (lambda (,_ignored ,place)
-                      (if (phpinspect-meta-overlay ,place)
-                          (push (phpinspect-meta-overlay ,place) ,bmap-stack)
-                        ,@body))
-                    (phpinspect-bmap-meta ,bmap)))))))
+    `(let ((,bmap ,(cadr place-and-bmap)))
+       (maphash (lambda (,_ignored ,place)
+                  ,@body
+                  (when (phpinspect-meta-overlay ,place)
+                    (phpinspect-splayt-traverse (,place 
(phpinspect-meta-children ,place))
+                      ,@body)))
+                (phpinspect-bmap-meta ,bmap)))))
 
 (defsubst phpinspect-bmap-register (bmap start end token &optional 
whitespace-before overlay)
   (let* ((starts (phpinspect-bmap-starts bmap))
@@ -198,7 +134,7 @@
          (meta (phpinspect-bmap-meta bmap))
          (last-token-start (phpinspect-bmap-last-token-start bmap))
          (existing-end (gethash end ends))
-         (token-meta (phpinspect-make-meta nil start end whitespace-before 
token overlay)))
+         (token-meta (or overlay (phpinspect-make-meta nil start end 
whitespace-before token overlay))))
     (unless whitespace-before
       (setq whitespace-before ""))
 
@@ -219,22 +155,9 @@
         (while (and (car stack) (>= (phpinspect-meta-start (car stack))
                                     start))
           (setq child (pop stack))
-          (setf (phpinspect-meta-parent child) token-meta)
-          (when (phpinspect-meta-overlay child)
-            (setf (phpinspect-meta-parent
-                   (phpinspect-overlay-token-meta
-                    (phpinspect-meta-overlay child)))
-                  token-meta))
-
-          (setf (phpinspect-meta-right-siblings child) right-siblings)
-          (when (phpinspect-meta-overlay child)
-            (setf (phpinspect-meta-right-siblings
-                   (phpinspect-overlay-token-meta
-                    (phpinspect-meta-overlay child)))
-                  right-siblings))
-          (push (phpinspect-meta-token child) right-siblings))
-
-        (setf (phpinspect-bmap-token-stack bmap) stack)))
+          (phpinspect-meta-set-parent child token-meta))
+
+          (setf (phpinspect-bmap-token-stack bmap) stack)))
 
     (setf (phpinspect-bmap-last-token-start bmap) start)
     (push token-meta (phpinspect-bmap-token-stack bmap))))
@@ -243,34 +166,9 @@
   (and (listp overlay)
        (eq 'overlay (car overlay))))
 
-(defsubst phpinspect-overlay-wrap-meta (overlay meta)
-  (when meta
-    (setq meta (cl-copy-list meta))
-    (setf (phpinspect-meta-start meta)
-          (+ (phpinspect-meta-start meta) (phpinspect-overlay-delta overlay)))
-    (setf (phpinspect-meta-end meta)
-          (+ (phpinspect-meta-end meta) (phpinspect-overlay-delta overlay)))
-
-    (when (phpinspect-meta-overlay meta)
-      (let ((meta-overlay (cl-copy-list (phpinspect-meta-overlay meta))))
-        (setf (phpinspect-overlay-start meta-overlay)
-              (+ (phpinspect-overlay-start meta-overlay)
-                 (phpinspect-overlay-delta overlay)))
-        (setf (phpinspect-overlay-end meta-overlay)
-              (+ (phpinspect-overlay-end meta-overlay)
-                 (phpinspect-overlay-delta overlay)))
-        (setf (phpinspect-overlay-delta meta-overlay)
-              (+ (phpinspect-overlay-delta meta-overlay)
-                 (phpinspect-overlay-delta overlay)))
-        (setf (phpinspect-meta-overlay meta) meta-overlay)))
-
-    meta))
-
 (cl-defmethod phpinspect-bmap-token-starting-at ((overlay (head overlay)) 
point)
-  (phpinspect-overlay-wrap-meta
-   overlay
-   (phpinspect-bmap-token-starting-at
-    (phpinspect-overlay-bmap overlay) (- point (phpinspect-overlay-delta 
overlay)))))
+  (phpinspect-bmap-token-starting-at
+   (phpinspect-overlay-bmap overlay) (- point (phpinspect-overlay-delta 
overlay))))
 
 (cl-defmethod phpinspect-bmap-token-starting-at ((bmap phpinspect-bmap) point)
   (let ((overlay (phpinspect-bmap-overlay-at-point bmap point)))
@@ -279,9 +177,8 @@
       (gethash point (phpinspect-bmap-starts bmap)))))
 
 (cl-defmethod phpinspect-bmap-tokens-ending-at ((overlay (head overlay)) point)
-  (mapcar (lambda (meta) (phpinspect-overlay-wrap-meta overlay meta))
-          (phpinspect-bmap-tokens-ending-at
-           (phpinspect-overlay-bmap overlay) (- point 
(phpinspect-overlay-delta overlay)))))
+  (phpinspect-bmap-tokens-ending-at
+   (phpinspect-overlay-bmap overlay) (- point (phpinspect-overlay-delta 
overlay))))
 
 (cl-defmethod phpinspect-bmap-tokens-ending-at ((bmap phpinspect-bmap) point)
   (let ((overlay (phpinspect-bmap-overlay-at-point bmap point)))
@@ -290,7 +187,7 @@
       (gethash point (phpinspect-bmap-ends bmap)))))
 
 (defsubst phpinspect-bmap-overlay-at-point (bmap point)
-  (let ((overlay (phpinspect-splayt-find (phpinspect-bmap-overlays bmap) point 
#'<= #'<= #'<=)))
+  (let ((overlay (phpinspect-splayt-find-smallest-after 
(phpinspect-bmap-overlays bmap) point)))
     (when (and overlay (phpinspect-overlay-overlaps-point overlay point))
       overlay)))
 
@@ -307,11 +204,7 @@
        (<= (phpinspect-meta-end meta) (phpinspect-overlay-end overlay))))
 
 (cl-defmethod phpinspect-bmap-token-meta ((overlay (head overlay)) token)
-  (let ((meta
-         (phpinspect-overlay-wrap-meta
-          overlay (phpinspect-bmap-token-meta (phpinspect-overlay-bmap 
overlay) token))))
-    (when (and meta (phpinspect-overlay-encloses-meta overlay meta))
-      meta)))
+  (phpinspect-bmap-token-meta (phpinspect-overlay-bmap overlay) token))
 
 (cl-defmethod phpinspect-bmap-token-meta ((bmap phpinspect-bmap) token)
   (unless (phpinspect-probably-token-p token)
@@ -322,6 +215,9 @@
         (catch 'found
           (phpinspect-splayt-traverse (overlay (phpinspect-bmap-overlays bmap))
             (when (setq found? (phpinspect-bmap-token-meta overlay token))
+              ;; Hit overlay's node to rebalance tree
+              (phpinspect-splayt-find
+               (phpinspect-bmap-overlays bmap) (phpinspect-overlay-end 
overlay))
               (throw 'found found?)))))))
 
 (defsubst phpinspect-probably-token-p (token)
@@ -357,7 +253,10 @@ giving up. If not provided, this is 100."
          (start (+ (phpinspect-meta-start token-meta) pos-delta))
          (end (+ (phpinspect-meta-end token-meta) pos-delta))
          (overlay `(overlay ,start ,end ,pos-delta ,bmap-overlay ,token-meta)))
-    (phpinspect-bmap-register bmap start end (phpinspect-meta-token 
token-meta) whitespace-before overlay)
+    (phpinspect-meta-detach-parent token-meta)
+    (phpinspect-meta-shift token-meta pos-delta)
+    (setf (phpinspect-meta-overlay token-meta) overlay)
+    (phpinspect-bmap-register bmap start end (phpinspect-meta-token 
token-meta) whitespace-before token-meta)
     (phpinspect-splayt-insert (phpinspect-bmap-overlays bmap) 
(phpinspect-overlay-end overlay) overlay)))
 
 (defun phpinspect-bmap-make-location-resolver (bmap)
diff --git a/phpinspect-eldoc.el b/phpinspect-eldoc.el
index 3e8ac35d26..ffdc5e8459 100644
--- a/phpinspect-eldoc.el
+++ b/phpinspect-eldoc.el
@@ -77,27 +77,28 @@ be implemented for return values of 
`phpinspect-eld-strategy-execute'")
             variable
             method
             result)
-        (cond ((phpinspect-static-attrib-p attrib)
-               (setq variable (phpinspect--class-get-variable class 
attribute-name))
-
-               (if (and variable
-                        (or (phpinspect--variable-static-p variable)
-                            (phpinspect--variable-const-p variable)))
-                   (setq result variable)
-                 (setq method (phpinspect--class-get-static-method
-                               class (phpinspect-intern-name attribute-name)))
-                 (when method
-                   (setq result (phpinspect-make-function-doc :fn method)))))
-              ((phpinspect-object-attrib-p attrib)
-               (setq variable (phpinspect--class-get-variable class 
attribute-name))
-
-               (if (and variable
-                        (phpinspect--variable-vanilla-p variable))
-                   (setq result variable)
-                 (setq method (phpinspect--class-get-method
-                               class (phpinspect-intern-name attribute-name)))
-                 (when method
-                   (setq result (phpinspect-make-function-doc :fn 
method))))))))))
+        (when attribute-name
+          (cond ((phpinspect-static-attrib-p attrib)
+                 (setq variable (phpinspect--class-get-variable class 
attribute-name))
+
+                 (if (and variable
+                          (or (phpinspect--variable-static-p variable)
+                              (phpinspect--variable-const-p variable)))
+                     (setq result variable)
+                   (setq method (phpinspect--class-get-static-method
+                                 class (phpinspect-intern-name 
attribute-name)))
+                   (when method
+                     (setq result (phpinspect-make-function-doc :fn method)))))
+                ((phpinspect-object-attrib-p attrib)
+                 (setq variable (phpinspect--class-get-variable class 
attribute-name))
+
+                 (if (and variable
+                          (phpinspect--variable-vanilla-p variable))
+                     (setq result variable)
+                   (setq method (phpinspect--class-get-method
+                                 class (phpinspect-intern-name 
attribute-name)))
+                   (when method
+                     (setq result (phpinspect-make-function-doc :fn 
method)))))))))))
 
 
 (cl-defstruct (phpinspect-eld-function-args (:constructor 
phpinspect-make-eld-function-args))
@@ -127,6 +128,7 @@ be implemented for return values of 
`phpinspect-eld-strategy-execute'")
          match-result static arg-list arg-pos)
 
     (phpinspect--log "Eldoc statement is:  %s" statement)
+    (phpinspect--log "Enclosing token was: %s" enclosing-token)
     (when enclosing-token
       (cond
        ;; Method call
diff --git a/phpinspect-meta.el b/phpinspect-meta.el
new file mode 100644
index 0000000000..03ce5767b7
--- /dev/null
+++ b/phpinspect-meta.el
@@ -0,0 +1,130 @@
+;;; phpinspect-meta.el --- PHP parsing and completion package  -*- 
lexical-binding: t; -*-
+
+;; Copyright (C) 2021  Free Software Foundation, Inc
+
+;; Author: Hugo Thunnissen <devel@hugot.nl>
+;; Keywords: php, languages, tools, convenience
+;; Version: 0
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'phpinspect-splayt)
+
+(define-inline phpinspect-make-meta
+  (parent start end whitespace-before token &optional overlay children 
parent-offset)
+  (inline-quote (list 'meta ,parent ,start ,end ,whitespace-before ,token 
,overlay
+                      ;;,children ,parent-offset)))
+                      (or ,children (phpinspect-make-splayt)) ,parent-offset)))
+
+(define-inline phpinspect-meta-parent (meta)
+  (inline-quote (cadr ,meta)))
+
+(define-inline phpinspect-meta-children (meta)
+  (inline-quote (car (nthcdr 7 ,meta))))
+
+(define-inline phpinspect-meta-parent-offset (meta)
+  (inline-quote (car (nthcdr 8 ,meta))))
+
+(define-inline phpinspect-meta-overlay (meta)
+  (inline-quote (car (nthcdr 6 ,meta))))
+
+(define-inline phpinspect-meta-token (meta)
+  (inline-quote (car (nthcdr 5 ,meta))))
+
+(define-inline phpinspect-meta-absolute-end (meta)
+  (inline-quote (cadddr ,meta)))
+
+(define-inline phpinspect-meta-whitespace-before (meta)
+  (inline-quote (car (cddddr ,meta))))
+
+(defun phpinspect-meta-start (meta)
+  (if (phpinspect-meta-parent meta)
+      (+ (phpinspect-meta-start (phpinspect-meta-parent meta))
+         (phpinspect-meta-parent-offset meta))
+    (phpinspect-meta-absolute-start meta)))
+
+(defun phpinspect-meta-end (meta)
+  (+ (phpinspect-meta-start meta) (phpinspect-meta-width meta)))
+
+(defsubst phpinspect-meta-width (meta)
+  (- (phpinspect-meta-absolute-end meta) (phpinspect-meta-absolute-start 
meta)))
+
+(defun phpinspect-meta-sort-width (meta1 meta2)
+  (< (phpinspect-meta-width meta1) (phpinspect-meta-width meta2)))
+
+(defun phpinspect-meta-sort-start (meta1 meta2)
+  (< (phpinspect-meta-start meta1) (phpinspect-meta-start meta2)))
+
+(define-inline phpinspect-meta-absolute-start (meta)
+  (inline-quote (caddr ,meta)))
+
+(defsubst phpinspect-meta-overlaps-point (meta point)
+  (and (> (phpinspect-meta-end meta) point)
+       (<= (phpinspect-meta-start meta) point)))
+
+(defun phpinspect-meta-find-parent-matching-token (meta predicate)
+  (if (funcall predicate (phpinspect-meta-token meta))
+      meta
+    (catch 'found
+      (while (phpinspect-meta-parent meta)
+        (setq meta (phpinspect-meta-parent meta))
+        (when (funcall predicate (phpinspect-meta-token meta))
+          (throw 'found meta))))))
+
+(define-inline phpinspect-meta-set-parent (meta parent)
+  (inline-letevals (meta parent)
+    (inline-quote
+     (progn
+       (when ,parent
+         (setf (phpinspect-meta-parent-offset ,meta)
+               (- (phpinspect-meta-start ,meta) (phpinspect-meta-start 
,parent)))
+         (phpinspect-meta-add-child ,parent ,meta))
+       (setcar (cdr ,meta) ,parent)))))
+
+;; Note: using defsubst here causes a byte code overflow
+(defun phpinspect-meta-add-child (meta child)
+  (phpinspect-splayt-insert (phpinspect-meta-children meta) 
(phpinspect-meta-parent-offset child) child))
+
+(define-inline phpinspect-meta-detach-parent (meta)
+  (inline-letevals (meta)
+    (inline-quote
+     (when (phpinspect-meta-parent ,meta)
+       ;; Update absolute start and end
+       (setf (phpinspect-meta-absolute-start ,meta) (phpinspect-meta-start 
,meta))
+       (setf (phpinspect-meta-absolute-end ,meta) (phpinspect-meta-end ,meta))
+       (setf (phpinspect-meta-parent ,meta) nil)))))
+
+(defun phpinspect-meta-shift (meta delta)
+  (setf (phpinspect-meta-absolute-start meta) (+ (phpinspect-meta-start meta) 
delta))
+  (setf (phpinspect-meta-absolute-end meta) (+ (phpinspect-meta-end meta) 
delta)))
+
+(defun phpinspect-meta-right-siblings (meta)
+  (mapcar #'phpinspect-meta-token
+          (sort
+           (phpinspect-splayt-find-all-after
+            (phpinspect-meta-children (phpinspect-meta-parent meta)) 
(phpinspect-meta-parent-offset meta))
+           #'phpinspect-meta-sort-start)))
+
+
+(defun phpinspect-meta-string (meta)
+  (format "[start: %d, end: %d, token: %s]"
+          (phpinspect-meta-start meta) (phpinspect-meta-end meta) 
(phpinspect-meta-token meta)))
+
+
+(provide 'phpinspect-meta)
+;;; phpinspect-meta.el ends here
diff --git a/phpinspect-resolvecontext.el b/phpinspect-resolvecontext.el
index 16dca768bc..fd66f68091 100644
--- a/phpinspect-resolvecontext.el
+++ b/phpinspect-resolvecontext.el
@@ -60,21 +60,24 @@
        (string= "return" (cadr token))))
 
 (defun phpinspect-find-statement-before-point (bmap meta point)
-  (let ((children (reverse (cdr (phpinspect-meta-token meta)))))
-    (let ((previous-siblings))
-      (catch 'return
-        (dolist (child children)
-          (when (phpinspect-probably-token-p child)
-            (setq child (phpinspect-bmap-token-meta bmap child))
-            (when (< (phpinspect-meta-start child) point)
-              (if (and (not previous-siblings) (phpinspect-blocklike-p 
(phpinspect-meta-token child)))
-                  (progn
-                    (throw 'return (phpinspect-find-statement-before-point 
bmap child point)))
-                (when (or (phpinspect-return-p (phpinspect-meta-token child))
-                          (phpinspect-end-of-statement-p 
(phpinspect-meta-token child)))
-                  (throw 'return previous-siblings))
-                (push (phpinspect-meta-token child) previous-siblings)))))
-        previous-siblings))))
+  (let ((children (reverse (cdr (phpinspect-meta-token meta))))
+        child-meta
+        previous-siblings)
+    (catch 'return
+      (dolist (child children)
+        (when (phpinspect-probably-token-p child)
+          (setq child-meta (phpinspect-bmap-token-meta bmap child))
+          (unless child-meta
+            (phpinspect--log "[ERROR] No metadata object found for token %s" 
child))
+          (when (< (phpinspect-meta-start child-meta) point)
+            (if (and (not previous-siblings) (phpinspect-blocklike-p child))
+                (progn
+                  (throw 'return (phpinspect-find-statement-before-point bmap 
child-meta point)))
+              (when (or (phpinspect-return-p child)
+                        (phpinspect-end-of-statement-p  child))
+                (throw 'return previous-siblings))
+              (push child previous-siblings)))))
+      previous-siblings)))
 
 (defun phpinspect--get-last-statement-in-token (token)
   (setq token (cond ((phpinspect-function-p token)
@@ -102,7 +105,10 @@
          (subject (phpinspect-bmap-last-token-before-point bmap point))
          (subject-token)
          (siblings))
-    (phpinspect--log "Last token before point: %s" (phpinspect-meta-token 
subject))
+    (phpinspect--log "Last token before point: %s, right siblings: %s, parent: 
%s"
+                     (phpinspect-meta-string subject)
+                     (phpinspect-meta-right-siblings subject)
+                     (phpinspect-meta-string (phpinspect-meta-parent subject)))
 
     (let ((next-sibling (car (phpinspect-meta-right-siblings subject))))
       ;; When the right sibling of the last ending token overlaps point, this 
is
diff --git a/phpinspect-splayt.el b/phpinspect-splayt.el
index fa96aa7f61..a6e7475212 100644
--- a/phpinspect-splayt.el
+++ b/phpinspect-splayt.el
@@ -27,192 +27,223 @@
 ;; Important functions:
 ;; - `phpinspect-splayt-insert'
 ;; - `phpinspect-splayt-find'
+;; - `phpinspect-splayt-find-smallest-after'
+;; - `phpinspect-splayt-find-all-after'
 ;; - `phpinspect-splayt-traverse'
+;;;
+;;
+;; DEVELOPING
+;;
+;; The main aim for this tree implementation is to be reasonably fast and
+;; comfortable to use for most of phpinspect's common operations. That means:
+;;
+;; - Fast insertion of sequential keys (for example when parsing a buffer from 
left to right)
+;; - Consing as few bytes as possible by keeping the data structure simple, to 
avoid GC pauses as much as possible
+;; - Fast repeated acces of "hot" regions (for example the edited region of a 
buffer)
+;; - A straight forward public API to retrieve sets of nodes
+;;
+;; ** Inline Functions **
+;; There is a lot of use of `define-inline' in this file. Most of these inlines
+;; improve performance significantly. This is especially true for smaller
+;; inlined functions. It might be possible to change one or two of the larger
+;; functions to normal defuns without reintroducing a lot of ovehead. If you
+;; want to do this to make debugging the code a little easier, and you can
+;; backup that it doesn't impact performance all that much with some benchmarks
+;; (especially parse-file.el in the benchmarks folder), your PR will be 
welcomed.
+;;
 
-;;; Code:
-
-(defsubst phpinspect-make-splayt-node (key value &optional left right)
-  (cons (cons key value) (cons left right)))
-
-(defsubst phpinspect-splayt-node-left (node)
-  (cadr node))
-
-(defsubst phpinspect-splayt-node-right (node)
-  (cddr node))
-
-(defsubst phpinspect-splayt-node-key (node)
-  (caar node))
-
-(defsubst phpinspect-splayt-node-value (node)
-  (cdar node))
-
-(gv-define-setter phpinspect-splayt-node-left (left node) `(setcar (cdr ,node) 
,left))
-(gv-define-setter phpinspect-splayt-node-right (right node) `(setcdr (cdr 
,node) ,right))
-(gv-define-setter phpinspect-splayt-node-key (key node) `(setcar (car ,node) 
,value))
-(gv-define-setter phpinspect-splayt-node-value (value node) `(setcdr (car 
,node) ,value))
-
-(defsubst phpinspect-splayt-node-update-parent (node parent new-val)
-  (if (eq node (phpinspect-splayt-node-left parent))
-      (setf (phpinspect-splayt-node-left parent) new-val)
-    (setf (phpinspect-splayt-node-right parent) new-val)))
-
-(defsubst phpinspect-make-splayt (&optional root-node)
-  (cons root-node nil))
-
-(defsubst phpinspect-splayt-root-node (splayt)
-  (car splayt))
 
-(gv-define-setter phpinspect-splayt-root-node (node splayt) `(setcar ,splayt 
,node))
+;;; Code:
 
-(defsubst phpinspect-splayt-node-rotate-right (node &optional parent splayt)
-  (let* ((left (phpinspect-splayt-node-left node))
-         (left-right (phpinspect-splayt-node-right left)))
-    (setf (phpinspect-splayt-node-right left) node)
-    (setf (phpinspect-splayt-node-left node) left-right)
-
-    (when (and splayt (eq node (phpinspect-splayt-root-node splayt)))
-      (setf (phpinspect-splayt-root-node splayt) left))
+(define-inline phpinspect-make-splayt-node (key value &optional left right 
parent temp-store)
+  (inline-quote (cons (cons ,key ,value) (list ,left ,right ,parent 
,temp-store))))
+
+(define-inline phpinspect-splayt-node-left (node)
+  (inline-quote (cadr ,node)))
 
-    (when parent
-      (phpinspect-splayt-node-update-parent node parent left))))
+(define-inline phpinspect-splayt-node-right (node)
+  (inline-quote (caddr ,node)))
 
-(defsubst phpinspect-splayt-node-rotate-left (node &optional parent splayt)
-  (let* ((right (phpinspect-splayt-node-right node))
-         (right-left (phpinspect-splayt-node-left right)))
-    (setf (phpinspect-splayt-node-left right) node)
-    (setf (phpinspect-splayt-node-right node) right-left)
-
-    (when (and splayt (eq node (phpinspect-splayt-root-node splayt)))
-      (setf (phpinspect-splayt-root-node splayt) right))
-
-    (when parent
-      (phpinspect-splayt-node-update-parent node parent right))))
-
-(defsubst phpinspect-make-splayt-nav (splayt &optional current-node parents)
-  (cons splayt (cons (or current-node (phpinspect-splayt-root-node splayt))
-                     parents)))
-
-(defsubst phpinspect-splayt-nav-splayt (nav)
-  (car nav))
-
-(defsubst phpinspect-splayt-nav-current (nav)
-  (cadr nav))
-
-(defsubst phpinspect-splayt-nav-parents (nav)
-  (cddr nav))
-
-(gv-define-setter phpinspect-splayt-nav-current (node nav) `(setcar (cdr ,nav) 
,node))
-(gv-define-setter phpinspect-splayt-nav-parents (parents nav) `(setcdr (cdr 
,nav) ,parents))
-
-(defsubst phpinspect-splayt-nav-right (nav)
-  (push (phpinspect-splayt-nav-current nav) (phpinspect-splayt-nav-parents 
nav))
-  (setf (phpinspect-splayt-nav-current nav)
-        (phpinspect-splayt-node-right (phpinspect-splayt-nav-current nav))))
-
-(defsubst phpinspect-splayt-nav-left (nav)
-  (push (phpinspect-splayt-nav-current nav) (phpinspect-splayt-nav-parents 
nav))
-  (setf (phpinspect-splayt-nav-current nav)
-        (phpinspect-splayt-node-left (phpinspect-splayt-nav-current nav))))
-
-(defsubst phpinspect-splayt-nav-has-left-p (nav)
-  (phpinspect-splayt-node-left (phpinspect-splayt-nav-current nav)))
-
-(defsubst phpinspect-splayt-nav-has-right-p (nav)
-  (phpinspect-splayt-node-right (phpinspect-splayt-nav-current nav)))
-
-(defsubst phpinspect-splayt-nav-up (nav)
-  (setf (phpinspect-splayt-nav-current nav)
-        (pop (phpinspect-splayt-nav-parents nav))))
-
-(defsubst phpinspect-splayt-nav-current-value (nav)
-  (phpinspect-splayt-node-value (phpinspect-splayt-nav-current nav)))
-
-(defsubst phpinspect-splayt-nav-current-key (nav)
-  (phpinspect-splayt-node-key (phpinspect-splayt-nav-current nav)))
-
-(defsubst phpinspect-splayt-insert (splayt key value)
-  (phpinspect-splayt-insert-node splayt (phpinspect-make-splayt-node key 
value)))
-
-(defsubst phpinspect-splay (splayt node parents)
-  (let (grandparent great-grandparent)
-    (while parents
-      (setq parent (pop parents))
-      (setq grandparent (pop parents))
-
-      (if grandparent
-          (cond
-           ;; Zig-Zig rotation
-           ((and (eq parent (phpinspect-splayt-node-left grandparent))
-                 (eq node (phpinspect-splayt-node-left parent)))
-            (phpinspect-splayt-node-rotate-right grandparent (car parents) 
splayt)
-            (phpinspect-splayt-node-rotate-right parent (car parents) splayt))
-
-           ;; Zag-Zag rotation
-           ((and (eq parent (phpinspect-splayt-node-right grandparent))
-                 (eq node (phpinspect-splayt-node-right parent)))
-            (phpinspect-splayt-node-rotate-left grandparent (car parents) 
splayt)
-            (phpinspect-splayt-node-rotate-left parent (car parents) splayt))
-
-           ;; Zig-Zag rotation
-           ((and (eq parent (phpinspect-splayt-node-right grandparent))
-                 (eq node (phpinspect-splayt-node-left parent)))
-            (phpinspect-splayt-node-rotate-right parent grandparent splayt)
-            (phpinspect-splayt-node-rotate-left grandparent (car parents) 
splayt))
-
-           ;; Zag-Zig rotation
-           ((and (eq parent (phpinspect-splayt-node-left grandparent))
-                 (eq node (phpinspect-splayt-node-right parent)))
-            (phpinspect-splayt-node-rotate-left parent grandparent splayt)
-            (phpinspect-splayt-node-rotate-right grandparent (car parents) 
splayt))
-           (t
-            (error "Failed in determining rotation strategy")))
-        ;; Else
-        (if (eq node (phpinspect-splayt-node-left parent))
-            (phpinspect-splayt-node-rotate-right parent (car parents) splayt)
-          (phpinspect-splayt-node-rotate-left parent (car parents) splayt))))))
-
-(defsubst phpinspect-splayt-insert-node (splayt node)
-  (if (not (phpinspect-splayt-root-node splayt))
-      (setf (phpinspect-splayt-root-node splayt) node)
-
-    ;; Else
-    (let ((nav (phpinspect-make-splayt-nav splayt)))
-      (catch 'break
-        (while t
-          (if (< (phpinspect-splayt-node-key node)
-                 (phpinspect-splayt-nav-current-key nav))
-              (if (phpinspect-splayt-nav-has-left-p nav)
-                  (phpinspect-splayt-nav-left nav)
-                (setf (phpinspect-splayt-node-left 
(phpinspect-splayt-nav-current nav))
-                      node)
-                (throw 'break nil))
-
-            ;; Else
-            (if (phpinspect-splayt-nav-has-right-p nav)
-                (phpinspect-splayt-nav-right nav)
-              (setf (phpinspect-splayt-node-right 
(phpinspect-splayt-nav-current nav))
-                    node)
-              (throw 'break nil))))))))
+(define-inline phpinspect-splayt-node-key (node)
+  (inline-quote (caar ,node)))
+
+(define-inline phpinspect-splayt-node-value (node)
+  (inline-quote (cdar ,node)))
+
+(define-inline phpinspect-splayt-node-parent (node)
+  (inline-quote (cadddr ,node)))
 
-(defmacro phpinspect-splayt-traverse (place-and-splayt &rest body)
-  "Traverse splay tree in cadr of PLACE-AND-SPLAYT, executing BODY.
-
-The car of PLACE-AND-SPLAYT is assigned the value of each node.
-
-Traversal is breadth-first to take advantage of the splay trees
-main benefit: the most accessed interval of keys is likely to be
-near the top of the tee."
+(define-inline phpinspect-splayt-node-temp-store (node)
+  "Dedicated place to store data when necessary. Mostly used for
+rotations without instantiating a lexical environment with
+`let'. When only used once or twice in a function call, this
+apeared to be a little more performant than using `let'."
+  (inline-quote (car (cddddr ,node))))
+
+(define-inline phpinspect-splayt-node-update-parent (node parent new-val)
+  (inline-letevals (node parent new-val)
+    (inline-quote
+     (if (eq ,node (phpinspect-splayt-node-left ,parent))
+         (setf (phpinspect-splayt-node-left ,parent) ,new-val)
+       (setf (phpinspect-splayt-node-right ,parent) ,new-val)))))
+
+(define-inline phpinspect-make-splayt (&optional root-node)
+  (inline-quote
+   (cons ,root-node nil)))
+
+(define-inline phpinspect-splayt-root-node (splayt)
+  (inline-quote (car ,splayt)))
+
+(define-inline phpinspect-splayt-node-rotate-right (node &optional splayt)
+  (inline-letevals (node splayt)
+    (inline-quote
+     (progn
+       ;; Save right node of left child
+       (setf (phpinspect-splayt-node-temp-store ,node)
+             (phpinspect-splayt-node-right (phpinspect-splayt-node-left 
,node)))
+
+       ;; Update node parent to reference left as child
+       (when (phpinspect-splayt-node-parent ,node)
+         (phpinspect-splayt-node-update-parent
+          ,node (phpinspect-splayt-node-parent ,node) 
(phpinspect-splayt-node-left ,node)))
+
+       ;; Set left node new parent
+       (setf (phpinspect-splayt-node-parent (phpinspect-splayt-node-left 
,node))
+             (phpinspect-splayt-node-parent ,node))
+
+       ;; Set left node as node's new parent
+       (setf (phpinspect-splayt-node-parent ,node)
+             (phpinspect-splayt-node-left ,node))
+
+       ;; Set node as left's right child
+       (setf (phpinspect-splayt-node-right (phpinspect-splayt-node-left 
,node)) ,node)
+
+       ;; Set left's right child as node's left child
+       (setf (phpinspect-splayt-node-left ,node) 
(phpinspect-splayt-node-temp-store ,node))
+
+       ;; Update new left child's parent
+       (when (phpinspect-splayt-node-left ,node)
+         (setf (phpinspect-splayt-node-parent (phpinspect-splayt-node-left 
,node)) ,node))
+
+       ;; Update root node of tree when necessary
+       (when (and ,splayt (eq ,node (phpinspect-splayt-root-node ,splayt)))
+         (setf (phpinspect-splayt-root-node ,splayt) 
(phpinspect-splayt-node-parent ,node)))))))
+
+(define-inline phpinspect-splayt-node-rotate-left (node &optional splayt)
+  (inline-letevals (node splayt)
+    (inline-quote
+     (progn
+       ;; Save left node of right child
+       (setf (phpinspect-splayt-node-temp-store ,node)
+             (phpinspect-splayt-node-left (phpinspect-splayt-node-right 
,node)))
+
+       ;; Update node parent to reference right as child
+       (when (phpinspect-splayt-node-parent ,node)
+         (phpinspect-splayt-node-update-parent
+          ,node (phpinspect-splayt-node-parent ,node) 
(phpinspect-splayt-node-right ,node)))
+
+       ;; Set right node new parent
+       (setf (phpinspect-splayt-node-parent (phpinspect-splayt-node-right 
,node))
+             (phpinspect-splayt-node-parent ,node))
+
+       ;; Set right node as node's new parent
+       (setf (phpinspect-splayt-node-parent ,node)
+             (phpinspect-splayt-node-right ,node))
+
+       ;; Set node as right's left child
+       (setf (phpinspect-splayt-node-left (phpinspect-splayt-node-right 
,node)) ,node)
+
+       ;; Set right's left child as node's  right child
+       (setf (phpinspect-splayt-node-right ,node) 
(phpinspect-splayt-node-temp-store ,node))
+
+       ;; Update new right child's parent
+       (when (phpinspect-splayt-node-right ,node)
+         (setf (phpinspect-splayt-node-parent (phpinspect-splayt-node-right 
,node)) ,node))
+
+       ;; Update root node of tree when necessary
+       (when (and ,splayt (eq ,node (phpinspect-splayt-root-node ,splayt)))
+         (setf (phpinspect-splayt-root-node ,splayt) 
(phpinspect-splayt-node-parent ,node)))))))
+
+(define-inline phpinspect-splayt-insert (splayt key value)
+  (inline-quote
+   (phpinspect-splayt-insert-node ,splayt (phpinspect-make-splayt-node ,key 
,value))))
+
+(define-inline phpinspect-splayt-node-grandparent (node)
+  (inline-quote (phpinspect-splayt-node-parent (phpinspect-splayt-node-parent 
,node))))
+
+(define-inline phpinspect-splay (splayt node)
+  (inline-letevals (splayt node)
+    (let ((parent (inline-quote (phpinspect-splayt-node-parent ,node)))
+          (grandparent (inline-quote (phpinspect-splayt-node-grandparent 
,node))))
+      (inline-quote
+       (progn
+         (while ,parent
+           (if (phpinspect-splayt-node-grandparent ,node)
+               (cond
+                ;; Zig-Zig rotation
+                ((and (eq ,parent (phpinspect-splayt-node-left ,grandparent))
+                      (eq ,node (phpinspect-splayt-node-left ,parent)))
+                 (phpinspect-splayt-node-rotate-right ,grandparent ,splayt)
+                 (phpinspect-splayt-node-rotate-right ,parent ,splayt))
+
+                ;; Zag-Zag rotation
+                ((and (eq (phpinspect-splayt-node-parent ,node)
+                          (phpinspect-splayt-node-right 
(phpinspect-splayt-node-grandparent ,node)))
+                      (eq ,node (phpinspect-splayt-node-right 
(phpinspect-splayt-node-parent ,node))))
+                 (phpinspect-splayt-node-rotate-left ,grandparent ,splayt)
+                 (phpinspect-splayt-node-rotate-left ,parent ,splayt))
+
+                ;; Zig-Zag rotation
+                ((and (eq ,parent (phpinspect-splayt-node-right ,grandparent))
+                      (eq ,node (phpinspect-splayt-node-left ,parent)))
+                 (phpinspect-splayt-node-rotate-right ,parent ,splayt)
+                 (phpinspect-splayt-node-rotate-left ,parent ,splayt))
+
+                ;; Zag-Zig rotation
+                ((and (eq ,parent (phpinspect-splayt-node-left ,grandparent))
+                      (eq ,node (phpinspect-splayt-node-right ,parent)))
+                 (phpinspect-splayt-node-rotate-left ,parent ,splayt)
+                 (phpinspect-splayt-node-rotate-right ,parent ,splayt))
+                (t
+                 (error "Failed in determining rotation strategy. 
(phpinspect-splayt-node-grandparent ,node): %s, parent: %s, ,node: %s")))
+
+             ;; Else
+             (if (eq ,node (phpinspect-splayt-node-left ,parent))
+                 (phpinspect-splayt-node-rotate-right ,parent ,splayt)
+               (phpinspect-splayt-node-rotate-left ,parent ,splayt))))
+
+         ,node)))))
+
+(define-inline phpinspect-splayt-insert-node (splayt node)
+  (inline-letevals (splayt node (parent (inline-quote 
(phpinspect-splayt-node-temp-store ,node))))
+    (inline-quote
+     (if (not (phpinspect-splayt-root-node ,splayt))
+         (setf (phpinspect-splayt-root-node ,splayt) ,node)
+       (progn
+         (setf ,parent (phpinspect-splayt-find-insertion-node ,splayt 
(phpinspect-splayt-node-key ,node)))
+         (unless ,parent
+           (error "Error: failed to find parent node for %s" ,node))
+
+         (setf (phpinspect-splayt-node-parent ,node) ,parent)
+         (if (< (phpinspect-splayt-node-key ,parent) 
(phpinspect-splayt-node-key ,node))
+             (setf (phpinspect-splayt-node-right ,parent) ,node)
+           (setf (phpinspect-splayt-node-left ,parent) ,node))
+
+         (phpinspect-splay ,splayt ,node))))))
+
+(defmacro phpinspect-splayt-node-traverse (place-and-node &rest body)
   (declare (indent 1))
-  (let ((place (car place-and-splayt))
+  (let ((place (car place-and-node))
         (current-sym (gensym))
-        (splayt-sym (gensym))
         (stack-sym (gensym))
         (queue-sym (gensym))
         (reverse-sym (gensym))
+        (node-sym (gensym))
         (size-sym (gensym)))
-    `(let* ((,splayt-sym ,(cadr place-and-splayt))
+    `(let* ((,node-sym ,(cadr place-and-node))
             ;; Make place locally scoped variable if a symbol
-            (,queue-sym (list (phpinspect-splayt-root-node ,splayt-sym)))
+            (,queue-sym (when ,node-sym
+                          (list ,node-sym)))
             (,reverse-sym t)
             ,size-sym
             ,stack-sym
@@ -231,10 +262,10 @@ near the top of the tee."
              ,@body)
 
            (when (phpinspect-splayt-node-right ,current-sym)
-             (setq ,queue-sym (nconc ,queue-sym (list 
(phpinspect-splayt-node-right ,current-sym)))))
+             (push (phpinspect-splayt-node-right ,current-sym) ,queue-sym))
 
            (when (phpinspect-splayt-node-left ,current-sym)
-             (setq ,queue-sym (nconc ,queue-sym (list 
(phpinspect-splayt-node-left ,current-sym)))))
+             (push (phpinspect-splayt-node-left ,current-sym) ,queue-sym))
 
            (setq ,size-sym (- ,size-sym 1)))
 
@@ -244,38 +275,110 @@ near the top of the tee."
              (setf ,place (phpinspect-splayt-node-value ,current-sym))
              ,@body))
 
-         (setq ,reverse-sym (not ,reverse-sym))))))
-
-(defsubst phpinspect-splayt-find (splayt key &optional navigator matcher 
continue-predicate)
-  (unless navigator (setq navigator #'<))
-  (unless matcher (setq matcher #'=))
-
-  (let ((nav (phpinspect-make-splayt-nav splayt))
-        current next)
-    (when (phpinspect-splayt-nav-current nav)
-      (catch 'found
-        (while t
-          (setq current (phpinspect-splayt-nav-current nav)
-                next nil)
-          (cond
-           ((funcall navigator key (phpinspect-splayt-nav-current-key nav))
-            (when (phpinspect-splayt-nav-has-left-p nav)
-              (phpinspect-splayt-nav-left nav)
-              (setq next (phpinspect-splayt-nav-current nav))))
-           (t
-            (when (phpinspect-splayt-nav-has-right-p nav)
-              (phpinspect-splayt-nav-right nav)
-              (setq next (phpinspect-splayt-nav-current nav)))))
-
-          (if (funcall matcher key (phpinspect-splayt-node-key current))
-              (when (or (not next)
-                        (not continue-predicate)
-                        (not (funcall continue-predicate key 
(phpinspect-splayt-node-key next))))
-                (phpinspect-splay
-                 splayt current
-                 (if next (cdr (phpinspect-splayt-nav-parents nav)) 
(phpinspect-splayt-nav-parents nav)))
-                (throw 'found (phpinspect-splayt-node-value current)))
-            (unless next
-              (throw 'found nil))))))))
+         (setq ,reverse-sym (not ,reverse-sym)))
+
+       nil)))
+
+(defmacro phpinspect-splayt-traverse (place-and-splayt &rest body)
+  "Traverse splay tree in cadr of PLACE-AND-SPLAYT, executing BODY.
+
+The car of PLACE-AND-SPLAYT is assigned the value of each node.
+
+Traversal is breadth-first to take advantage of the splay trees
+main benefit: the most accessed interval of keys is likely to be
+near the top of the tee."
+  (declare (indent 1))
+  `(phpinspect-splayt-node-traverse
+       (,(car place-and-splayt) (phpinspect-splayt-root-node ,(cadr 
place-and-splayt)))
+     ,@body))
+
+(define-inline phpinspect-splayt-find-node (splayt key)
+  (inline-letevals (splayt key)
+    (inline-quote
+     (let ((current (phpinspect-splayt-root-node ,splayt)))
+       (catch 'return
+         (while current
+           (if (= ,key (phpinspect-splayt-node-key current))
+               (progn
+                 (phpinspect-splay ,splayt current)
+                 (throw 'return current))
+             (if (< ,key (phpinspect-splayt-node-key current))
+                 (setq current (phpinspect-splayt-node-left current))
+               (setq current (phpinspect-splayt-node-right current))))))))))
+
+(define-inline phpinspect-splayt-find-insertion-node (splayt key)
+  (inline-letevals (splayt key)
+    (inline-quote
+     (let ((current (phpinspect-splayt-root-node ,splayt)))
+       (catch 'return
+         (while current
+           (if (or (and (> (phpinspect-splayt-node-key current) ,key)
+                        (not (phpinspect-splayt-node-left current)))
+                   (and (<= (phpinspect-splayt-node-key current) ,key)
+                        (not (phpinspect-splayt-node-right current))))
+               (throw 'return current)
+             (if (< ,key (phpinspect-splayt-node-key current))
+                 (setq current (phpinspect-splayt-node-left current))
+               (setq current (phpinspect-splayt-node-right current))))))))))
+
+(define-inline phpinspect-splayt-find-smallest-node-after (splayt key)
+  (inline-letevals (splayt key)
+    (inline-quote
+     (let ((current (phpinspect-splayt-root-node ,splayt))
+           smallest)
+
+       (catch 'break
+         (while current
+           (if (>= ,key  (phpinspect-splayt-node-key current))
+               (setf current (phpinspect-splayt-node-right current)
+                     smallest current)
+             (throw 'break nil))))
+
+       (catch 'return
+         (while current
+           (when (= (+ ,key 1) (phpinspect-splayt-node-key current))
+             (throw 'return current))
+
+           (cond ((and (phpinspect-splayt-node-parent current)
+                       (< ,key (phpinspect-splayt-node-key 
(phpinspect-splayt-node-parent current)))
+                       (eq (phpinspect-splayt-node-right 
(phpinspect-splayt-node-parent current))
+                           current))
+                  (setf current (phpinspect-splayt-node-parent current)
+                        smallest current))
+                 ((phpinspect-splayt-node-left current)
+                  (setf current (phpinspect-splayt-node-left current))
+                  (when (< ,key (phpinspect-splayt-node-key current))
+                    (setf smallest current)))
+                 ((>= ,key (phpinspect-splayt-node-key current))
+                  (if (phpinspect-splayt-node-right current)
+                      (setf current (phpinspect-splayt-node-right current))
+                    (throw 'return smallest)))
+                 (t (throw 'return smallest)))))))))
+
+(defsubst phpinspect-splayt-find-all-after (splayt key)
+  "Find all values in SPLAYT with a key higher than KEY."
+  (let ((first (phpinspect-splayt-find-smallest-node-after splayt key))
+        all)
+    (while first
+      (push (phpinspect-splayt-node-value first) all)
+
+      (phpinspect-splayt-node-traverse (sibling (phpinspect-splayt-node-right 
first))
+        (setq all (nconc all (list sibling))))
+
+      (if (and (phpinspect-splayt-node-parent first)
+               (eq first (phpinspect-splayt-node-left 
(phpinspect-splayt-node-parent first))))
+          (setq first (phpinspect-splayt-node-parent first))
+        (setq first nil)))
+    all))
+
+(define-inline phpinspect-splayt-find-smallest-after (splayt key)
+  "Find value of node with smallest key that is higher than KEY in SPLAYT."
+  (inline-quote
+   (phpinspect-splayt-node-value
+    (phpinspect-splay
+     ,splayt (phpinspect-splayt-find-smallest-node-after ,splayt ,key)))))
+
+(defsubst phpinspect-splayt-find (splayt key)
+  (phpinspect-splayt-node-value (phpinspect-splayt-find-node splayt key)))
 
 (provide 'phpinspect-splayt)
diff --git a/test/test-bmap.el b/test/test-bmap.el
index 700564a25b..613efaecfd 100644
--- a/test/test-bmap.el
+++ b/test/test-bmap.el
@@ -94,6 +94,9 @@
     (phpinspect-bmap-overlay
      bmap bmap2 (phpinspect-bmap-token-starting-at bmap2 200) 20)
 
+    (phpinspect-bmap-overlay
+     bmap bmap2 (phpinspect-bmap-token-starting-at bmap2 220) 20)
+
     (setq result (phpinspect-bmap-tokens-overlapping bmap 240))
     (should (equal '((:token6) (:token5)) (mapcar #'phpinspect-meta-token 
result)))
 
diff --git a/test/test-splayt.el b/test/test-splayt.el
index c399f7c1c5..8bc9829136 100644
--- a/test/test-splayt.el
+++ b/test/test-splayt.el
@@ -27,24 +27,30 @@
 
 (ert-deftest phpinspect-splayt-node-rotate ()
   (let* ((one (phpinspect-make-splayt-node 1 "one"))
-         (node (phpinspect-make-splayt-node
+         (four (phpinspect-make-splayt-node 4 "four"))
+         (three (phpinspect-make-splayt-node
                 3 "three"
                 one
-                (phpinspect-make-splayt-node 4 "four"))))
-    (phpinspect-splayt-node-rotate-right node)
-    (should (equal (phpinspect-make-splayt-node
-                    1 "one" nil
-                    (phpinspect-make-splayt-node
-                     3 "three" nil (phpinspect-make-splayt-node 4 "four")))
-                   one))
-
-    (phpinspect-splayt-node-rotate-left node one)
-
-    (should (equal (phpinspect-make-splayt-node
-                    1 "one" nil
-                    (phpinspect-make-splayt-node
-                     4 "four" (phpinspect-make-splayt-node 3 "three")))
-                   one))))
+                four)))
+    (setf (phpinspect-splayt-node-parent four) three)
+    (setf (phpinspect-splayt-node-parent one) three)
+    (phpinspect-splayt-node-rotate-right three)
+
+    (should (eq one (phpinspect-splayt-node-parent three)))
+    (should (eq three (phpinspect-splayt-node-parent four)))
+    (should (eq three (phpinspect-splayt-node-right one)))
+    (should (eq four (phpinspect-splayt-node-right three)))
+    (should-not (phpinspect-splayt-node-left one))
+    (should-not (phpinspect-splayt-node-left four))
+    (should-not (phpinspect-splayt-node-left three))
+
+    (phpinspect-splayt-node-rotate-left one)
+
+    (should (eq one (phpinspect-splayt-node-left three)))
+    (should (eq three (phpinspect-splayt-node-parent four)))
+    (should (eq three (phpinspect-splayt-node-parent one)))
+    (should (eq four (phpinspect-splayt-node-right three)))
+    (should (eq one (phpinspect-splayt-node-left three)))))
 
 (ert-deftest phpinspect-splayt ()
   (let ((tree (phpinspect-make-splayt)))
@@ -63,7 +69,17 @@
     (should (string= "nine" (phpinspect-splayt-find tree 9)))
     (should (string= "four" (phpinspect-splayt-find tree 4)))
     (should (string= "twelve" (phpinspect-splayt-find tree 12)))
-    (should (string= "eleven" (phpinspect-splayt-find tree 11)))))
+    (should (string= "eleven" (phpinspect-splayt-find tree 11)))
+
+    (let ((expected (sort '("nine" "three" "eleven" "eight" "twelve" "four" 
"one") #'string-lessp))
+          (result))
+
+      (phpinspect-splayt-traverse (item tree)
+        (push item result))
+
+      (setq result (sort result #'string-lessp))
+
+      (should (equal expected result)))))
 
 (ert-deftest phpinspect-splayt-traverse ()
   (let ((tree (phpinspect-make-splayt)))
@@ -84,3 +100,31 @@
       (setq result (sort result #'string-lessp))
 
       (should (equal expected result)))))
+
+(ert-deftest phpinspect-splayt-find-smallest-after ()
+  (let ((tree (phpinspect-make-splayt)))
+    (phpinspect-splayt-insert tree 9 "nine")
+    (phpinspect-splayt-insert tree 3 "three")
+    (phpinspect-splayt-insert tree 11 "eleven")
+    (phpinspect-splayt-insert tree 8 "eight")
+    (phpinspect-splayt-insert tree 12 "twelve")
+    (phpinspect-splayt-insert tree 4 "four")
+    (phpinspect-splayt-insert tree 1 "one")
+
+
+    (should (string= "nine" (phpinspect-splayt-find-smallest-after tree 8)))
+    (should (string= "three" (phpinspect-splayt-find-smallest-after tree 1)))))
+
+(ert-deftest phpinspect-splayt-find-all-after ()
+  (let ((tree (phpinspect-make-splayt)))
+    (phpinspect-splayt-insert tree 9 "nine")
+    (phpinspect-splayt-insert tree 3 "three")
+    (phpinspect-splayt-insert tree 11 "eleven")
+    (phpinspect-splayt-insert tree 8 "eight")
+    (phpinspect-splayt-insert tree 12 "twelve")
+    (phpinspect-splayt-insert tree 4 "four")
+    (phpinspect-splayt-insert tree 1 "one")
+
+
+    (should (equal (sort '("eight" "nine" "eleven" "twelve") #'string-lessp)
+                   (sort (phpinspect-splayt-find-all-after tree 7) 
#'string-lessp)))))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]