3 (defun for-each (func tree forwardp)
4 (let ((iter (make-iterator tree :forwardp forwardp)))
5 (declare (type function iter))
6 (loop (multiple-value-bind (node morep) (funcall iter)
7 (unless morep (return-from for-each (values)))
8 (funcall func (datum node))))))
10 (defun tree-for-each (func tree)
11 (for-each func tree t))
13 (defun reverse-tree-for-each (func tree)
14 (for-each func tree nil))
16 ;;; We implement this directly in terms of iterators, rather than
17 ;;; re-using TREE-FOR-EACH, so that we can provide for GO tags in the
18 ;;; body of the loop, similarly to DO/DOTIMES/DOLIST.
19 (defmacro dotree ((obj-var tree-var &optional return-value) &body body)
23 `(let* ((,tree ,tree-var)
24 (,iter (make-iterator ,tree :forwardp t)))
25 (declare (type function ,iter))
26 (do ((,node (funcall ,iter) (funcall ,iter)))
27 ((null ,node) ,return-value)
28 (let ((,obj-var (datum ,node)))
33 (defmacro do-tree-range ((obj-var tree-var
36 (upper nil)) &body body)
37 (macrolet ((invalid-type (type)
38 `(error "Invalid :type supplied to DO-TREE-RANGE: ~A" ,type)))
39 (let* ((node (gensym))
50 `(upper-bound-node-with-path ,lower ,tree t))
52 `(select-node-with-path ,tree ,lower))
53 (t (invalid-type type)))
55 ((or (eq type :key) (eq type :index))
56 `(minimum-node ,tree-var (root ,tree)))
57 (t (invalid-type type)))))
61 `(upper-bound-node ,upper ,tree))
63 `(select-node ,tree ,upper))
64 (t (invalid-type type)))
66 ((or (eq type :key) (eq type :index)) nil)
67 (t (invalid-type type))))))
68 `(let ((,tree ,tree-var))
69 (multiple-value-bind (,current ,stack) ,lower-exp
71 with ,iterator = (make-iterator ,tree :forwardp t
74 with ,last = ,upper-exp
75 do (multiple-value-bind (,node ,morep) (funcall ,iterator)
76 (when (or (not ,morep)
79 (let ((,obj-var (datum ,node)))
83 ;;; FIXME: FROM-END isn't necessarily very intuitive here. find out
84 ;;; how regular CL sequence functions treat it (especially with indices)
85 ;;; and rewrite the macro to match.
86 (defmacro with-tree-iterator ((iter tree &key
87 (from-end nil) (type :key) (start nil))
89 "Like WITH-HASH-TABLE-ITERATOR; ITER is a name defined via MACROLET
90 and TREE is a form evaluated to produce a tree. Successive calls to ITER
91 return the items in the tree, one by one.
93 (ITER) two values. The first is a boolean that is true if an object from
94 the tree is returned; the second is an object stored in the tree.
96 TYPE can be either :KEY or :INDEX and defines how to interpret START. If
97 TYPE is :KEY and START is specified, then START is taken to be some key of
98 the tree from which iteration should begin. If no such key exists, then
99 the next greatest key is chosen as the starting point. If TYPE is :INDEX,
100 and START is specified, then START is taken to be an index passed to
101 SELECT-NODE to determine from what object iteration should begin.
103 If START is not specified, iteration begins from the minimum node of TREE.
105 FROM-END is currently broken and should not be used."
106 (let ((treesym (gensym))
109 (let* ((,treesym ,tree)
113 `(lower-bound-node ,start ,treesym)
114 `(minimum-node ,treesym (root-node ,treesym))))
117 `(select-node ,start ,treesym)
118 `(minimum-node ,treesym (root-node ,treesym)))))))
120 (multiple-value-prog1
121 (values (not (null-node-p node ,treesym))
123 (setf node (tree-successor node)))))
125 (macrolet ((,iter () '(funcall ,n-iter)))
129 (defun reduce (tree function
131 (initial-value nil valuep)
133 (let ((accum (if valuep
135 (funcall function))))
136 (flet ((left-reducer (object)
137 (setf accum (funcall function accum (if key
140 (right-reducer (object)
141 (setf accum (funcall function (if key
144 (declare (dynamic-extent #'left-reducer #'right-reducer))
146 (reverse-tree-for-each #'right-reducer tree)
147 (tree-for-each #'left-reducer tree))
150 (defun position (key tree &key from-end)
151 (multiple-value-bind (node stack item-key) (find-insertion-point tree key)
152 (declare (ignore item-key))
155 (loop with position = (1- (rank node))
157 unless (eq (cdr entry) 'left)
158 do (incf position (rank (car entry)))
161 (- (size tree) position)