aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorDaniel Colascione2015-03-01 23:57:51 -0800
committerDaniel Colascione2015-03-02 15:42:09 -0800
commitf6b5db6c45b773f86e203368aee9153ec8527205 (patch)
tree360651305d19be6356d2912d29bbaad88f4529f9 /test
parent9d8d0658147dfe5a90e2fb07ff666f35b1162d6e (diff)
downloademacs-f6b5db6c45b773f86e203368aee9153ec8527205.tar.gz
emacs-f6b5db6c45b773f86e203368aee9153ec8527205.zip
Add support for generators
diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index 78f7e34..e7d79d5 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog @@ -1,3 +1,8 @@ +2015-03-02 Daniel Colascione <dancol@dancol.org> + + * control.texi (Generators): New section + * elisp.text: Reference new section. + 2015-02-28 Eli Zaretskii <eliz@gnu.org> * searching.texi (Char Classes): Update the documentation of diff --git a/doc/misc/ChangeLog b/doc/misc/ChangeLog index 448c7f2..4e9c119 100644 --- a/doc/misc/ChangeLog +++ b/doc/misc/ChangeLog @@ -1,3 +1,7 @@ +2015-03-02 Daniel Colascione <dancol@dancol.org> + + * cl.texi (Iteration Clauses): Mention iterator support. + 2015-02-25 Tassilo Horn <tsdh@gnu.org> * reftex.texi (Multifile Documents): Document diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 7ce2e81..4ab4406 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,6 +1,8 @@ 2015-03-02 Daniel Colascione <dancol@dancol.org> - * vc/vc.el (vc-responsible-backend): Add autoload cooking for + * emacs-lisp/generator.el: New file. + + * vc/vc.el (vc-responsible-backend): Add autoload cookie for `vc-responsible-backend'. 2015-03-01 Michael Albinus <michael.albinus@gmx.de> diff --git a/test/ChangeLog b/test/ChangeLog index 684e98f..64ad851 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,5 +1,7 @@ 2015-03-02 Daniel Colascione <dancol@dancol.org> + * automated/generator-tests.el: New tests + * automated/finalizer-tests.el (finalizer-basic) (finalizer-circular-reference, finalizer-cross-reference) (finalizer-error): New tests.
Diffstat (limited to 'test')
-rw-r--r--test/ChangeLog2
-rw-r--r--test/automated/generator-tests.el288
2 files changed, 290 insertions, 0 deletions
diff --git a/test/ChangeLog b/test/ChangeLog
index 684e98f880e..64ad85198af 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,5 +1,7 @@
12015-03-02 Daniel Colascione <dancol@dancol.org> 12015-03-02 Daniel Colascione <dancol@dancol.org>
2 2
3 * automated/generator-tests.el: New tests
4
3 * automated/finalizer-tests.el (finalizer-basic) 5 * automated/finalizer-tests.el (finalizer-basic)
4 (finalizer-circular-reference, finalizer-cross-reference) 6 (finalizer-circular-reference, finalizer-cross-reference)
5 (finalizer-error): New tests. 7 (finalizer-error): New tests.
diff --git a/test/automated/generator-tests.el b/test/automated/generator-tests.el
new file mode 100644
index 00000000000..2c5de31b40b
--- /dev/null
+++ b/test/automated/generator-tests.el
@@ -0,0 +1,288 @@
1;;; generator-tests.el --- Testing generators -*- lexical-binding: t -*-
2
3;; Copyright (C) 2015 Free Software Foundation, Inc.
4
5;; Author: Daniel Colascione <dancol@dancol.org>
6;; Keywords:
7
8;; This program is free software; you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by
10;; the Free Software Foundation, either version 3 of the License, or
11;; (at your option) any later version.
12
13;; This program is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details.
17
18;; You should have received a copy of the GNU General Public License
19;; along with this program. If not, see <http://www.gnu.org/licenses/>.
20
21;;; Commentary:
22
23(require 'generator)
24(require 'ert)
25(require 'cl-lib)
26
27(defun generator-list-subrs ()
28 (cl-loop for x being the symbols
29 when (and (fboundp x)
30 (cps--special-form-p (symbol-function x)))
31 collect x))
32
33(defmacro cps-testcase (name &rest body)
34 "Perform a simple test of the continuation-transforming code.
35
36`cps-testcase' defines an ERT testcase called NAME that evaluates
37BODY twice: once using ordinary `eval' and once using
38lambda-generators. The test ensures that the two forms produce
39identical output.
40"
41 `(progn
42 (ert-deftest ,name ()
43 (should
44 (equal
45 (funcall (lambda () ,@body))
46 (iter-next
47 (funcall
48 (iter-lambda () (iter-yield (progn ,@body))))))))
49 (ert-deftest ,(intern (format "%s-noopt" name)) ()
50 (should
51 (equal
52 (funcall (lambda () ,@body))
53 (iter-next
54 (funcall
55 (let ((cps-disable-atomic-optimization t))
56 (iter-lambda () (iter-yield (progn ,@body)))))))))))
57
58(put 'cps-testcase 'lisp-indent-function 1)
59
60(defvar *cps-test-i* nil)
61(defun cps-get-test-i ()
62 *cps-test-i*)
63
64(cps-testcase cps-simple-1 (progn 1 2 3))
65(cps-testcase cps-empty-progn (progn))
66(cps-testcase cps-inline-not-progn (inline 1 2 3))
67(cps-testcase cps-prog1-a (prog1 1 2 3))
68(cps-testcase cps-prog1-b (prog1 1))
69(cps-testcase cps-prog1-c (prog2 1 2 3))
70(cps-testcase cps-quote (progn 'hello))
71(cps-testcase cps-function (progn #'hello))
72
73(cps-testcase cps-and-fail (and 1 nil 2))
74(cps-testcase cps-and-succeed (and 1 2 3))
75(cps-testcase cps-and-empty (and))
76
77(cps-testcase cps-or-fallthrough (or nil 1 2))
78(cps-testcase cps-or-alltrue (or 1 2 3))
79(cps-testcase cps-or-empty (or))
80
81(cps-testcase cps-let* (let* ((i 10)) i))
82(cps-testcase cps-let*-shadow-empty (let* ((i 10)) (let (i) i)))
83(cps-testcase cps-let (let ((i 10)) i))
84(cps-testcase cps-let-shadow-empty (let ((i 10)) (let (i) i)))
85(cps-testcase cps-let-novars (let nil 42))
86(cps-testcase cps-let*-novars (let* nil 42))
87
88(cps-testcase cps-let-parallel
89 (let ((a 5) (b 6)) (let ((a b) (b a)) (list a b))))
90
91(cps-testcase cps-let*-parallel
92 (let* ((a 5) (b 6)) (let* ((a b) (b a)) (list a b))))
93
94(cps-testcase cps-while-dynamic
95 (setq *cps-test-i* 0)
96 (while (< *cps-test-i* 10)
97 (setf *cps-test-i* (+ *cps-test-i* 1)))
98 *cps-test-i*)
99
100(cps-testcase cps-while-lexical
101 (let* ((i 0) (j 10))
102 (while (< i 10)
103 (setf i (+ i 1))
104 (setf j (+ j (* i 10))))
105 j))
106
107(cps-testcase cps-while-incf
108 (let* ((i 0) (j 10))
109 (while (< i 10)
110 (incf i)
111 (setf j (+ j (* i 10))))
112 j))
113
114(cps-testcase cps-dynbind
115 (setf *cps-test-i* 0)
116 (let* ((*cps-test-i* 5))
117 (cps-get-test-i)))
118
119(cps-testcase cps-nested-application
120 (+ (+ 3 5) 1))
121
122(cps-testcase cps-unwind-protect
123 (setf *cps-test-i* 0)
124 (unwind-protect
125 (setf *cps-test-i* 1)
126 (setf *cps-test-i* 2))
127 *cps-test-i*)
128
129(cps-testcase cps-catch-unused
130 (catch 'mytag 42))
131
132(cps-testcase cps-catch-thrown
133 (1+ (catch 'mytag
134 (throw 'mytag (+ 2 2)))))
135
136(cps-testcase cps-loop
137 (cl-loop for x from 1 to 10 collect x))
138
139(cps-testcase cps-loop-backquote
140 `(a b ,(cl-loop for x from 1 to 10 collect x) -1))
141
142(cps-testcase cps-if-branch-a
143 (if t 'abc))
144
145(cps-testcase cps-if-branch-b
146 (if t 'abc 'def))
147
148(cps-testcase cps-if-condition-fail
149 (if nil 'abc 'def))
150
151(cps-testcase cps-cond-empty
152 (cond))
153
154(cps-testcase cps-cond-atomi
155 (cond (42)))
156
157(cps-testcase cps-cond-complex
158 (cond (nil 22) ((1+ 1) 42) (t 'bad)))
159
160(put 'cps-test-error 'error-conditions '(cps-test-condition))
161
162(cps-testcase cps-condition-case
163 (condition-case
164 condvar
165 (signal 'cps-test-error 'test-data)
166 (cps-test-condition condvar)))
167
168(cps-testcase cps-condition-case-no-error
169 (condition-case
170 condvar
171 42
172 (cps-test-condition condvar)))
173
174(ert-deftest cps-generator-basic ()
175 (let* ((gen (iter-lambda ()
176 (iter-yield 1)
177 (iter-yield 2)
178 (iter-yield 3)
179 4))
180 (gen-inst (funcall gen)))
181 (should (eql (iter-next gen-inst) 1))
182 (should (eql (iter-next gen-inst) 2))
183 (should (eql (iter-next gen-inst) 3))
184
185 ;; should-error doesn't catch the generator-end condition (which
186 ;; isn't an error), so we write our own.
187 (let (errored)
188 (condition-case x
189 (iter-next gen-inst)
190 (iter-end-of-sequence
191 (setf errored (cdr x))))
192 (should (eql errored 4)))))
193
194(iter-defun mygenerator (i)
195 (iter-yield 1)
196 (iter-yield i)
197 (iter-yield 2))
198
199(ert-deftest cps-test-iter-do ()
200 (let (mylist)
201 (iter-do (x (mygenerator 4))
202 (push x mylist))
203
204 (assert (equal mylist '(2 4 1)))))
205
206(iter-defun gen-using-yield-value ()
207 (let (f)
208 (setf f (iter-yield 42))
209 (iter-yield f)
210 -8))
211
212(ert-deftest cps-yield-value ()
213 (let ((it (gen-using-yield-value)))
214 (should (eql (iter-next it -1) 42))
215 (should (eql (iter-next it -1) -1))))
216
217(ert-deftest cps-loop ()
218 (should
219 (equal (cl-loop for x iter-by (mygenerator 42)
220 collect x)
221 '(1 42 2))))
222
223(iter-defun gen-using-yield-from ()
224 (let ((sub-iter (gen-using-yield-value)))
225 (iter-yield (1+ (iter-yield-from sub-iter)))))
226
227(ert-deftest cps-test-yield-from-works ()
228 (let ((it (gen-using-yield-from)))
229 (should (eql (iter-next it -1) 42))
230 (should (eql (iter-next it -1) -1))
231 (should (eql (iter-next it -1) -7))))
232
233(defvar cps-test-closed-flag nil)
234
235(ert-deftest cps-test-iter-close ()
236 (garbage-collect)
237 (let ((cps-test-closed-flag nil))
238 (let ((iter (funcall
239 (iter-lambda ()
240 (unwind-protect (iter-yield 1)
241 (setf cps-test-closed-flag t))))))
242 (should (equal (iter-next iter) 1))
243 (should (not cps-test-closed-flag))
244 (iter-close iter)
245 (should cps-test-closed-flag))))
246
247(ert-deftest cps-test-iter-close-idempotent ()
248 (garbage-collect)
249 (let ((cps-test-closed-flag nil))
250 (let ((iter (funcall
251 (iter-lambda ()
252 (unwind-protect (iter-yield 1)
253 (setf cps-test-closed-flag t))))))
254 (should (equal (iter-next iter) 1))
255 (should (not cps-test-closed-flag))
256 (iter-close iter)
257 (should cps-test-closed-flag)
258 (setf cps-test-closed-flag nil)
259 (iter-close iter)
260 (should (not cps-test-closed-flag)))))
261
262(ert-deftest cps-test-iter-close-finalizer ()
263 (skip-unless gc-precise-p)
264 (garbage-collect)
265 (let ((cps-test-closed-flag nil))
266 (let ((iter (funcall
267 (iter-lambda ()
268 (unwind-protect (iter-yield 1)
269 (setf cps-test-closed-flag t))))))
270 (should (equal (iter-next iter) 1))
271 (should (not cps-test-closed-flag))
272 (setf iter nil)
273 (garbage-collect)
274 (should cps-test-closed-flag))))
275
276(ert-deftest cps-test-iter-cleanup-once-only ()
277 (let* ((nr-unwound 0)
278 (iter
279 (funcall (iter-lambda ()
280 (unwind-protect
281 (progn
282 (iter-yield 1)
283 (error "test")
284 (iter-yield 2))
285 (incf nr-unwound))))))
286 (should (equal (iter-next iter) 1))
287 (should-error (iter-next iter))
288 (should (equal nr-unwound 1))))