-
Notifications
You must be signed in to change notification settings - Fork 0
/
do.lisp
66 lines (60 loc) · 2.91 KB
/
do.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
(in-package #:iterator)
(defmacro do-iterator ((elementf object iterator-form &optional result)
&body body)
(let ((objectg (gensym "OBJECT")) (iterator (gensym "ITERATOR"))
(limit (gensym "LIMIT"))
(step (gensym "STEP")) (endp (gensym "ENDP"))
(elt (gensym "ELT")) (setelt (gensym "SETELT")))
`(let ((,objectg ,object))
(multiple-value-bind (,iterator ,limit ,step ,endp ,elt ,setelt)
,iterator-form
(declare (type function ,step ,endp ,elt ,setelt))
(flet ((,elementf () (funcall ,elt ,objectg ,iterator))
((setf ,elementf) (nv)
(funcall ,setelt nv ,objectg ,iterator)))
(declare (dynamic-extent #',elementf #'(setf ,elementf))
(ignorable #',elementf #'(setf ,elementf)))
(do ()
((funcall ,endp ,objectg ,iterator ,limit) ,result)
,@body
(setf ,iterator (funcall ,step ,objectg ,iterator))))))))
(defmacro do-iterator-elements ((var object iterator-form &optional result)
&body body)
(let ((eltf (gensym "ELEMENTF")))
`(do-iterator (,eltf ,object ,iterator-form ,result)
(let ((,var (,eltf))) (tagbody ,@body)))))
(defmacro do-iteration ((elementf (object &rest kwargs &key &allow-other-keys)
&optional result)
&body body)
(let ((objectg (gensym "OBJECT")) (iterator (gensym "ITERATOR"))
(limit (gensym "LIMIT"))
(step (gensym "STEP")) (endp (gensym "ENDP"))
(elt (gensym "ELT")) (setelt (gensym "SETELT")))
`(let ((,objectg ,object))
(with-iterator (,iterator ,limit ,endp ,elt ,setelt) (,objectg ,@kwargs)
(flet ((,elementf () (funcall ,elt ,objectg ,iterator))
((setf ,elementf) (nv)
(funcall ,setelt nv ,objectg ,iterator)))
(declare (dynamic-extent #',elementf #'(setf ,elementf)))
(do ()
((funcall ,endp ,objectg ,iterator ,limit) ,result)
,@body
(setf ,iterator (funcall ,step ,objectg ,iterator))))))))
(defmacro do-elements ((var (object &rest kwargs &key &allow-other-keys)
&optional result)
&body body)
(let ((eltf (gensym "ELEMENTF")))
`(do-iteration (,eltf (,object ,@kwargs) ,result)
(let ((,var (,eltf))) (tagbody ,@body)))))
;;;
(defmacro do-accumulator ((accumf accumulator-form) &body body)
(let ((idx (gensym "IDX"))
(accum (gensym "ACCUMULATOR")) (add (gensym "ADD"))
(finalize (gensym "FINALIZE")))
`(multiple-value-bind (,accum ,idx ,add ,finalize) ,accumulator-form
(block nil
(flet ((,accumf (new-value)
(setf ,idx (funcall ,add new-value ,accum ,idx))))
(declare (dynamic-extent #',accumf))
(tagbody ,@body)))
(funcall ,finalize ,accum ,idx))))