Optimize splay tree and use it to store token's children
ci/woodpecker/push/woodpecker Pipeline was successful Details

WIP-cache
Hugo Thunnissen 10 months ago
parent ab6954faf5
commit 0596bc52bf

@ -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)))

@ -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))))

@ -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)

@ -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

@ -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

@ -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

@ -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)

@ -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)))

@ -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)))))

Loading…
Cancel
Save