-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfor.lisp
39 lines (35 loc) · 1.29 KB
/
for.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
(in-package #:org.shirakumo.for)
(defvar *environment*)
(defmacro with-for-tagbody (body &body exit)
(let ((for-start (gensym "FOR-START"))
(for-end (gensym "FOR-END")))
`(macrolet ((end-for () `(go ,',for-end))
(skip-for () `(go ,',for-start)))
(tagbody
,for-start
,body
(go ,for-start)
,for-end
(progn ,@exit)))))
(defmacro with-for-block (() &body body)
`(block NIL
(macrolet ((return-for (&rest values)
(cond ((not values) `(return NIL))
((cdr values) `(return (values ,@values)))
(T `(return ,(first values))))))
,@body)))
(defmacro for (&environment env bindings &body body)
(let ((*environment* env))
(multiple-value-bind (bind-init bind-forms bind-exit bind-post) (convert-bindings bindings)
(multiple-value-bind (clause-init body-forms clause-exit) (convert-clauses body)
`(with-interleaving
,@bind-init
,@clause-init
(with-for-block ()
(with-for-tagbody
(progn ,@bind-forms
,@body-forms
,@bind-post)
(return-for
,@clause-exit
,@bind-exit))))))))