Commit | Line | Data |
---|---|---|
92a61010 | 1 | ;;;; elisp-compiler.test --- Test the compiler for Elisp. -*- scheme -*- |
d158fa62 | 2 | ;;;; |
92a61010 | 3 | ;;;; Copyright (C) 2009, 2010 Free Software Foundation, Inc. |
d158fa62 DK |
4 | ;;;; Daniel Kraft |
5 | ;;;; | |
6 | ;;;; This library is free software; you can redistribute it and/or | |
7 | ;;;; modify it under the terms of the GNU Lesser General Public | |
8 | ;;;; License as published by the Free Software Foundation; either | |
9 | ;;;; version 3 of the License, or (at your option) any later version. | |
10 | ;;;; | |
11 | ;;;; This library is distributed in the hope that it will be useful, | |
12 | ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | ;;;; Lesser General Public License for more details. | |
15 | ;;;; | |
16 | ;;;; You should have received a copy of the GNU Lesser General Public | |
17 | ;;;; License along with this library; if not, write to the Free Software | |
18 | ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
19 | ||
20 | (define-module (test-elisp-compiler) | |
21 | :use-module (test-suite lib) | |
22 | :use-module (system base compile) | |
23 | :use-module (language elisp runtime)) | |
24 | ||
25 | ||
26 | ; Macros to handle the compilation conveniently. | |
27 | ||
28 | (define-syntax compile-test | |
450cb504 | 29 | (syntax-rules (pass-if pass-if-equal pass-if-exception) |
d158fa62 DK |
30 | ((_ (pass-if test-name exp)) |
31 | (pass-if test-name (compile 'exp #:from 'elisp #:to 'value))) | |
a0899974 DK |
32 | ((_ (pass-if test-name exp #:opts opts)) |
33 | (pass-if test-name (compile 'exp #:from 'elisp #:to 'value #:opts opts))) | |
d158fa62 DK |
34 | ((_ (pass-if-equal test-name result exp)) |
35 | (pass-if test-name (equal? result | |
36 | (compile 'exp #:from 'elisp #:to 'value)))) | |
37 | ((_ (pass-if-exception test-name exc exp)) | |
38 | (pass-if-exception test-name exc | |
ccf7563f RT |
39 | (compile 'exp #:from 'elisp #:to 'value))) |
40 | ((_ (expect-fail test-name exp)) | |
41 | #f))) | |
d158fa62 DK |
42 | |
43 | (define-syntax with-test-prefix/compile | |
44 | (syntax-rules () | |
45 | ((_ section-name exp ...) | |
46 | (with-test-prefix section-name (compile-test exp) ...)))) | |
47 | ||
48 | ||
49 | ; Test control structures. | |
50 | ; ======================== | |
51 | ||
f6e0a4a6 BT |
52 | (compile '(%set-lexical-binding-mode #nil) #:from 'elisp #:to 'value) |
53 | ||
d158fa62 DK |
54 | (with-test-prefix/compile "Sequencing" |
55 | ||
56 | (pass-if-equal "progn" 1 | |
57 | (progn (setq a 0) | |
58 | (setq a (1+ a)) | |
fb66a47a DK |
59 | a)) |
60 | ||
d5ac6923 BT |
61 | (pass-if-equal "empty progn" #nil |
62 | (progn)) | |
63 | ||
fb66a47a DK |
64 | (pass-if "prog1" |
65 | (progn (setq a 0) | |
66 | (setq b (prog1 a (setq a (1+ a)))) | |
67 | (and (= a 1) (= b 0)))) | |
68 | ||
69 | (pass-if "prog2" | |
70 | (progn (setq a 0) | |
71 | (setq b (prog2 (setq a (1+ a)) | |
72 | (setq a (1+ a)) | |
73 | (setq a (1+ a)))) | |
74 | (and (= a 3) (= b 2))))) | |
d158fa62 DK |
75 | |
76 | (with-test-prefix/compile "Conditionals" | |
77 | ||
78 | (pass-if-equal "succeeding if" 1 | |
79 | (if t 1 2)) | |
7d1a9782 DK |
80 | (pass-if "failing if" |
81 | (and (= (if nil | |
82 | 1 | |
83 | (setq a 2) (setq a (1+ a)) a) | |
84 | 3) | |
85 | (equal (if nil 1) nil))) | |
86 | ||
d5ac6923 BT |
87 | (pass-if-equal "if with no else" #nil |
88 | (if nil t)) | |
89 | ||
d158fa62 DK |
90 | (pass-if-equal "empty cond" nil-value |
91 | (cond)) | |
92 | (pass-if-equal "all failing cond" nil-value | |
93 | (cond (nil) (nil))) | |
94 | (pass-if-equal "only condition" 5 | |
95 | (cond (nil) (5))) | |
96 | (pass-if-equal "succeeding cond value" 42 | |
97 | (cond (nil) (t 42) (t 0))) | |
98 | (pass-if-equal "succeeding cond side-effect" 42 | |
99 | (progn (setq a 0) | |
100 | (cond (nil) (t (setq a 42) 1) (t (setq a 0))) | |
101 | a))) | |
102 | ||
103 | (with-test-prefix/compile "Combining Conditions" | |
104 | ||
105 | (pass-if-equal "empty and" t-value (and)) | |
106 | (pass-if-equal "failing and" nil-value (and 1 2 nil 3)) | |
107 | (pass-if-equal "succeeding and" 3 (and 1 2 3)) | |
108 | ||
109 | (pass-if-equal "empty or" nil-value (or)) | |
110 | (pass-if-equal "failing or" nil-value (or nil nil nil)) | |
b6b9d596 DK |
111 | (pass-if-equal "succeeding or" 1 (or nil 1 nil 2 nil 3)) |
112 | ||
113 | (pass-if-equal "not true" nil-value (not 1)) | |
114 | (pass-if-equal "not false" t-value (not nil))) | |
d158fa62 DK |
115 | |
116 | (with-test-prefix/compile "Iteration" | |
117 | ||
118 | (pass-if-equal "failing while" 0 | |
119 | (progn (setq a 0) | |
120 | (while nil (setq a 1)) | |
121 | a)) | |
122 | (pass-if-equal "running while" 120 | |
123 | (progn (setq prod 1 | |
124 | i 1) | |
125 | (while (<= i 5) | |
126 | (setq prod (* i prod)) | |
127 | (setq i (1+ i))) | |
a338fa3d | 128 | prod))) |
d158fa62 | 129 | |
35b2e41d DK |
130 | (with-test-prefix/compile "Exceptions" |
131 | ||
132 | (pass-if "catch without exception" | |
133 | (and (setq a 0) | |
134 | (= (catch 'foobar | |
135 | (setq a (1+ a)) | |
136 | (setq a (1+ a)) | |
137 | a) | |
138 | 2) | |
139 | (= (catch (+ 1 2) a) 2))) | |
140 | ||
141 | ; FIXME: Figure out how to do this... | |
142 | ;(pass-if-exception "uncaught exception" 'elisp-exception | |
143 | ; (throw 'abc 1)) | |
144 | ||
145 | (pass-if "catch and throw" | |
146 | (and (setq mylist '(1 2)) | |
147 | (= (catch 'abc (throw 'abc 2) 1) 2) | |
33da12ee | 148 | (= (catch 'abc (catch 'def (throw 'abc (1+ 0)) 2) 3) 1) |
35b2e41d | 149 | (= (catch 'abc (catch 'def (throw 'def 1) 2) 3) 3) |
59e46065 | 150 | (= (catch mylist (catch (list 1 2) (throw mylist 1) 2) 3) 1))) |
33da12ee DK |
151 | |
152 | (pass-if "unwind-protect" | |
153 | (progn (setq a 0 b 1 c 1) | |
154 | (catch 'exc | |
155 | (unwind-protect (progn (setq a 1) | |
156 | (throw 'exc 0)) | |
157 | (setq a 0) | |
158 | (setq b 0))) | |
159 | (unwind-protect nil (setq c 0)) | |
160 | (and (= a 0) (= b 0) (= c 0) | |
161 | (= (unwind-protect 42 1 2 3) 42))))) | |
35b2e41d | 162 | |
e96a9591 DK |
163 | (with-test-prefix/compile "Eval" |
164 | ||
165 | (pass-if-equal "basic eval" 3 | |
166 | (progn (setq code '(+ 1 2)) | |
167 | (eval code))) | |
168 | ||
169 | (pass-if "real dynamic code" | |
170 | (and (setq a 1 b 1 c 1) | |
171 | (defun set-code (var val) | |
172 | (list 'setq var val)) | |
173 | (= a 1) (= b 1) (= c 1) | |
174 | (eval (set-code 'a '(+ 2 3))) | |
175 | (eval (set-code 'c 42)) | |
176 | (= a 5) (= b 1) (= c 42))) | |
177 | ||
178 | ; Build code that recursively again and again calls eval. What we want is | |
179 | ; something like: | |
180 | ; (eval '(1+ (eval '(1+ (eval 1))))) | |
181 | (pass-if "recursive eval" | |
182 | (progn (setq depth 10 i depth) | |
183 | (setq code '(eval 0)) | |
184 | (while (not (zerop i)) | |
0dbfdeef | 185 | (setq code (#{`}# (eval (quote (1+ (#{,}# code)))))) |
e96a9591 DK |
186 | (setq i (1- i))) |
187 | (= (eval code) depth)))) | |
188 | ||
d158fa62 DK |
189 | |
190 | ; Test handling of variables. | |
191 | ; =========================== | |
192 | ||
193 | (with-test-prefix/compile "Variable Setting/Referencing" | |
194 | ||
195 | ; TODO: Check for variable-void error | |
196 | ||
197 | (pass-if-equal "setq and reference" 6 | |
570c12ac DK |
198 | (progn (setq a 1 b 2 c 3) |
199 | (+ a b c))) | |
e96a9591 DK |
200 | (pass-if-equal "setq evaluation order" 1 |
201 | (progn (setq a 0 b 0) | |
202 | (setq a 1 b a))) | |
570c12ac | 203 | (pass-if-equal "setq value" 2 |
37099846 DK |
204 | (progn (setq a 1 b 2))) |
205 | ||
206 | (pass-if "set and symbol-value" | |
207 | (progn (setq myvar 'a) | |
208 | (and (= (set myvar 42) 42) | |
209 | (= a 42) | |
210 | (= (symbol-value myvar) 42)))) | |
211 | (pass-if "void variables" | |
212 | (progn (setq a 1 b 2) | |
213 | (and (eq (makunbound 'b) 'b) | |
214 | (boundp 'a) | |
3f70b2dc | 215 | (not (boundp 'b)))))) |
d158fa62 DK |
216 | |
217 | (with-test-prefix/compile "Let and Let*" | |
218 | ||
219 | (pass-if-equal "let without value" nil-value | |
220 | (let (a (b 5)) a)) | |
221 | (pass-if-equal "basic let" 0 | |
222 | (progn (setq a 0) | |
223 | (let ((a 1) | |
224 | (b a)) | |
225 | b))) | |
fd40f371 | 226 | |
d5ac6923 BT |
227 | (pass-if-equal "empty let" #nil (let ())) |
228 | ||
fd40f371 | 229 | (pass-if "let*" |
d158fa62 | 230 | (progn (setq a 0) |
fd40f371 DK |
231 | (and (let* ((a 1) |
232 | (b a)) | |
233 | (= b 1)) | |
234 | (let* (a b) | |
235 | (setq a 1 b 2) | |
236 | (and (= a 1) (= b 2))) | |
237 | (= a 0) | |
238 | (not (boundp 'b))))) | |
d158fa62 | 239 | |
d5ac6923 BT |
240 | (pass-if-equal "empty let*" #nil |
241 | (let* ())) | |
242 | ||
d158fa62 DK |
243 | (pass-if "local scope" |
244 | (progn (setq a 0) | |
245 | (setq b (let (a) | |
246 | (setq a 1) | |
247 | a)) | |
248 | (and (= a 0) | |
249 | (= b 1))))) | |
250 | ||
a6a5cf03 DK |
251 | (with-test-prefix/compile "Lexical Scoping" |
252 | ||
253 | (pass-if "basic let semantics" | |
254 | (and (setq a 1) | |
255 | (lexical-let ((a 2) (b a)) | |
256 | (and (= a 2) (= b 1))) | |
257 | (lexical-let* ((a 2) (b a)) | |
258 | (and (= a 2) (= b 2) (setq a 42) (= a 42))) | |
259 | (= a 1))) | |
260 | ||
261 | (pass-if "lexical scope with lexical-let's" | |
262 | (and (setq a 1) | |
263 | (defun dyna () a) | |
264 | (lexical-let (a) | |
265 | (setq a 2) | |
266 | (and (= a 2) (= (dyna) 1))) | |
267 | (= a 1) | |
268 | (lexical-let* (a) | |
269 | (setq a 2) | |
270 | (and (= a 2) (= (dyna) 1))) | |
271 | (= a 1))) | |
272 | ||
273 | (pass-if "lexical scoping vs. symbol-value / set" | |
274 | (and (setq a 1) | |
275 | (lexical-let ((a 2)) | |
276 | (and (= a 2) | |
277 | (= (symbol-value 'a) 1) | |
278 | (set 'a 3) | |
279 | (= a 2) | |
280 | (= (symbol-value 'a) 3))) | |
281 | (= a 3))) | |
282 | ||
283 | (pass-if "let inside lexical-let" | |
284 | (and (setq a 1 b 1) | |
285 | (defun dynvals () (cons a b)) | |
286 | (lexical-let ((a 2)) | |
287 | (and (= a 2) (equal (dynvals) '(1 . 1)) | |
288 | (let ((a 3) (b a)) | |
f6e0a4a6 | 289 | (declare (lexical a)) |
a6a5cf03 DK |
290 | (and (= a 3) (= b 2) |
291 | (equal (dynvals) '(1 . 2)))) | |
292 | (let* ((a 4) (b a)) | |
f6e0a4a6 | 293 | (declare (lexical a)) |
a6a5cf03 DK |
294 | (and (= a 4) (= b 4) |
295 | (equal (dynvals) '(1 . 4)))) | |
296 | (= a 2))) | |
297 | (= a 1))) | |
298 | ||
299 | (pass-if "lambda args inside lexical-let" | |
300 | (and (setq a 1) | |
301 | (defun dyna () a) | |
302 | (lexical-let ((a 2) (b 42)) | |
303 | (and (= a 2) (= (dyna) 1) | |
f6e0a4a6 BT |
304 | ((lambda (a) |
305 | (declare (lexical a)) | |
306 | (and (= a 3) (= b 42) (= (dyna) 1))) 3) | |
dfbc6e9d | 307 | ((lambda () (let ((a 3)) |
f6e0a4a6 | 308 | (declare (lexical a)) |
dfbc6e9d | 309 | (and (= a 3) (= (dyna) 1))))) |
a6a5cf03 DK |
310 | (= a 2) (= (dyna) 1))) |
311 | (= a 1))) | |
312 | ||
313 | (pass-if "closures" | |
314 | (and (defun make-counter () | |
315 | (lexical-let ((cnt 0)) | |
316 | (lambda () | |
317 | (setq cnt (1+ cnt))))) | |
318 | (setq c1 (make-counter) c2 (make-counter)) | |
ce305387 DK |
319 | (= (funcall c1) 1) |
320 | (= (funcall c1) 2) | |
321 | (= (funcall c1) 3) | |
322 | (= (funcall c2) 1) | |
323 | (= (funcall c2) 2) | |
324 | (= (funcall c1) 4) | |
c808c926 DK |
325 | (= (funcall c2) 3))) |
326 | ||
dfbc6e9d DK |
327 | (pass-if "lexical lambda args" |
328 | (progn (setq a 1 b 1) | |
329 | (defun dyna () a) | |
330 | (defun dynb () b) | |
e5a361d1 | 331 | (lexical-let (a c) |
dfbc6e9d | 332 | ((lambda (a b &optional c) |
f6e0a4a6 | 333 | (declare (lexical a c)) |
dfbc6e9d DK |
334 | (and (= a 3) (= (dyna) 1) |
335 | (= b 2) (= (dynb) 2) | |
336 | (= c 1))) | |
337 | 3 2 1)))) | |
338 | ||
339 | ; Check if a lambda without dynamically bound arguments | |
340 | ; is tail-optimized by doing a deep recursion that would otherwise overflow | |
341 | ; the stack. | |
342 | (pass-if "lexical lambda tail-recursion" | |
e5a361d1 | 343 | (lexical-let (i) |
dfbc6e9d DK |
344 | (setq to 1000000) |
345 | (defun iteration-1 (i) | |
f6e0a4a6 | 346 | (declare (lexical i)) |
dfbc6e9d DK |
347 | (if (< i to) |
348 | (iteration-1 (1+ i)))) | |
349 | (iteration-1 0) | |
350 | (setq x 0) | |
351 | (defun iteration-2 () | |
352 | (if (< x to) | |
353 | (setq x (1+ x)) | |
354 | (iteration-2))) | |
355 | (iteration-2) | |
356 | t))) | |
357 | ||
a6a5cf03 | 358 | |
d158fa62 DK |
359 | (with-test-prefix/compile "defconst and defvar" |
360 | ||
361 | (pass-if-equal "defconst without docstring" 3.141 | |
362 | (progn (setq pi 3) | |
363 | (defconst pi 3.141) | |
364 | pi)) | |
365 | (pass-if-equal "defconst value" 'pi | |
366 | (defconst pi 3.141 "Pi")) | |
367 | ||
368 | (pass-if-equal "defvar without value" 42 | |
369 | (progn (setq a 42) | |
370 | (defvar a) | |
371 | a)) | |
372 | (pass-if-equal "defvar on already defined variable" 42 | |
373 | (progn (setq a 42) | |
374 | (defvar a 1 "Some docstring is also ok") | |
375 | a)) | |
d158fa62 | 376 | (pass-if-equal "defvar on undefined variable" 1 |
37099846 DK |
377 | (progn (makunbound 'a) |
378 | (defvar a 1) | |
d158fa62 DK |
379 | a)) |
380 | (pass-if-equal "defvar value" 'a | |
381 | (defvar a))) | |
382 | ||
383 | ||
384 | ; Functions and lambda expressions. | |
385 | ; ================================= | |
386 | ||
387 | (with-test-prefix/compile "Lambda Expressions" | |
388 | ||
389 | (pass-if-equal "required arguments" 3 | |
390 | ((lambda (a b c) c) 1 2 3)) | |
391 | ||
392 | (pass-if-equal "optional argument" 3 | |
48489836 | 393 | ((lambda (a &optional b c) c) 1 2 3)) |
d158fa62 DK |
394 | (pass-if-equal "optional missing" nil-value |
395 | ((lambda (&optional a) a))) | |
396 | ||
397 | (pass-if-equal "rest argument" '(3 4 5) | |
398 | ((lambda (a b &rest c) c) 1 2 3 4 5)) | |
16318179 BT |
399 | (pass-if "rest missing" |
400 | (null ((lambda (a b &rest c) c) 1 2))) | |
d5ac6923 BT |
401 | |
402 | (pass-if-equal "empty lambda" #nil | |
403 | ((lambda ())))) | |
d158fa62 DK |
404 | |
405 | (with-test-prefix/compile "Function Definitions" | |
406 | ||
407 | (pass-if-equal "defun" 3 | |
408 | (progn (defun test (a b) (+ a b)) | |
409 | (test 1 2))) | |
410 | (pass-if-equal "defun value" 'test | |
37099846 DK |
411 | (defun test (a b) (+ a b))) |
412 | ||
413 | (pass-if "fset and symbol-function" | |
414 | (progn (setq myfunc 'x x 5) | |
415 | (and (= (fset myfunc 42) 42) | |
416 | (= (symbol-function myfunc) 42) | |
417 | (= x 5)))) | |
418 | (pass-if "void function values" | |
419 | (progn (setq a 1) | |
420 | (defun test (a b) (+ a b)) | |
421 | (fmakunbound 'a) | |
422 | (fset 'b 5) | |
423 | (and (fboundp 'b) (fboundp 'test) | |
424 | (not (fboundp 'a)) | |
e8f18b3f DK |
425 | (= a 1)))) |
426 | ||
0a32abc4 | 427 | (pass-if "flet" |
e8f18b3f DK |
428 | (progn (defun foobar () 42) |
429 | (defun test () (foobar)) | |
430 | (and (= (test) 42) | |
0e5b7e74 BT |
431 | (flet ((foobar () 0) |
432 | (myfoo () | |
433 | (funcall (symbol-function 'foobar)))) | |
e8f18b3f | 434 | (and (= (myfoo) 42) |
c6920dc8 | 435 | (= (test) 42))) |
0e5b7e74 | 436 | (flet ((foobar () nil)) |
e8f18b3f | 437 | (defun foobar () 0) |
c6920dc8 | 438 | (= (test) 42)) |
e8f18b3f | 439 | (= (test) 42))))) |
d158fa62 DK |
440 | |
441 | (with-test-prefix/compile "Calling Functions" | |
442 | ||
443 | (pass-if-equal "recursion" 120 | |
444 | (progn (defun factorial (n prod) | |
445 | (if (zerop n) | |
446 | prod | |
447 | (factorial (1- n) (* prod n)))) | |
448 | (factorial 5 1))) | |
449 | ||
450 | (pass-if "dynamic scoping" | |
451 | (progn (setq a 0) | |
452 | (defun foo () | |
453 | (setq a (1+ a)) | |
454 | a) | |
455 | (defun bar (a) | |
456 | (foo)) | |
457 | (and (= 43 (bar 42)) | |
e96a9591 DK |
458 | (zerop a)))) |
459 | ||
460 | (pass-if "funcall and apply argument handling" | |
461 | (and (defun allid (&rest args) args) | |
462 | (setq allid-var (symbol-function 'allid)) | |
463 | (equal (funcall allid-var 1 2 3) '(1 2 3)) | |
464 | (equal (funcall allid-var) nil) | |
465 | (equal (funcall allid-var 1 2 '(3 4)) '(1 2 (3 4))) | |
466 | (equal (funcall allid-var '()) '(())) | |
467 | (equal (apply allid-var 1 2 '(3 4)) '(1 2 3 4)) | |
468 | (equal (apply allid-var '(1 2)) '(1 2)) | |
469 | (equal (apply allid-var '()) nil))) | |
470 | ||
471 | (pass-if "raw functions with funcall" | |
472 | (and (= (funcall '+ 1 2) 3) | |
473 | (= (funcall (lambda (a b) (+ a b)) 1 2) 3) | |
474 | (= (funcall '(lambda (a b) (+ a b)) 1 2) 3)))) | |
b6b9d596 DK |
475 | |
476 | ||
9b5ff6a6 DK |
477 | ; Quoting and Backquotation. |
478 | ; ========================== | |
479 | ||
480 | (with-test-prefix/compile "Quotation" | |
481 | ||
482 | (pass-if "quote" | |
483 | (and (equal '42 42) (equal '"abc" "abc") | |
484 | (equal '(1 2 (3 (4) x)) '(1 2 (3 (4) x))) | |
485 | (not (equal '(1 2 (3 4 (x))) '(1 2 3 4 x))) | |
486 | (equal '(1 2 . 3) '(1 2 . 3)))) | |
487 | ||
488 | (pass-if "simple backquote" | |
0dbfdeef BT |
489 | (and (equal (#{`}# 42) 42) |
490 | (equal (#{`}# (1 (a))) '(1 (a))) | |
491 | (equal (#{`}# (1 . 2)) '(1 . 2)))) | |
9b5ff6a6 DK |
492 | (pass-if "unquote" |
493 | (progn (setq a 42 l '(18 12)) | |
0dbfdeef BT |
494 | (and (equal (#{`}# (#{,}# a)) 42) |
495 | (equal (#{`}# (1 a ((#{,}# l)) . (#{,}# a))) '(1 a ((18 12)) . 42))))) | |
9b5ff6a6 DK |
496 | (pass-if "unquote splicing" |
497 | (progn (setq l '(18 12) empty '()) | |
0dbfdeef BT |
498 | (and (equal (#{`}# (#{,@}# l)) '(18 12)) |
499 | (equal (#{`}# (l 2 (3 (#{,@}# l)) ((#{,@}# l)) (#{,@}# l))) | |
9b5ff6a6 | 500 | '(l 2 (3 18 12) (18 12) 18 12)) |
0dbfdeef | 501 | (equal (#{`}# (1 2 (#{,@}# empty) 3)) '(1 2 3)))))) |
9b5ff6a6 DK |
502 | |
503 | ||
504 | ||
74c009da DK |
505 | ; Macros. |
506 | ; ======= | |
507 | ||
508 | (with-test-prefix/compile "Macros" | |
509 | ||
510 | (pass-if-equal "defmacro value" 'magic-number | |
511 | (defmacro magic-number () 42)) | |
512 | ||
513 | (pass-if-equal "macro expansion" 1 | |
514 | (progn (defmacro take-first (a b) a) | |
515 | (take-first 1 (/ 1 0))))) | |
516 | ||
517 | ||
b6b9d596 DK |
518 | ; Test the built-ins. |
519 | ; =================== | |
520 | ||
e905e490 DK |
521 | (with-test-prefix/compile "Equivalence Predicates" |
522 | ||
523 | (pass-if "equal" | |
524 | (and (equal 2 2) (not (equal 1 2)) | |
525 | (equal "abc" "abc") (not (equal "abc" "ABC")) | |
526 | (equal 'abc 'abc) (not (equal 'abc 'def)) | |
527 | (equal '(1 2 (3 4) 5) '(1 2 (3 4) 5)) | |
528 | (not (equal '(1 2 3 4 5) '(1 2 (3 4) 5))))) | |
529 | ||
530 | (pass-if "eq" | |
531 | (progn (setq some-list '(1 2)) | |
532 | (setq some-string "abc") | |
533 | (and (eq 2 2) (not (eq 1 2)) | |
534 | (eq 'abc 'abc) (not (eq 'abc 'def)) | |
59e46065 BT |
535 | (eq some-string some-string) (not (eq some-string (string 97 98 99))) |
536 | (eq some-list some-list) (not (eq some-list (list 1 2))))))) | |
e905e490 | 537 | |
b6b9d596 DK |
538 | (with-test-prefix/compile "Number Built-Ins" |
539 | ||
540 | (pass-if "floatp" | |
541 | (and (floatp 1.0) (not (floatp 1)) (not (floatp 'a)))) | |
542 | (pass-if "integerp" | |
543 | (and (integerp 42) (integerp -2) (not (integerp 1.0)))) | |
544 | (pass-if "numberp" | |
545 | (and (numberp 1.0) (numberp -2) (not (numberp 'a)))) | |
546 | (pass-if "wholenump" | |
547 | (and (wholenump 0) (not (wholenump -2)) (not (wholenump 1.0)))) | |
548 | (pass-if "zerop" | |
549 | (and (zerop 0) (zerop 0.0) (not (zerop 1)))) | |
550 | ||
551 | (pass-if "comparisons" | |
552 | (and (= 1 1.0) (/= 0 1) | |
553 | (< 1 2) (> 2 1) (>= 1 1) (<= 1 1) | |
554 | (not (< 1 1)) (not (<= 2 1)))) | |
555 | ||
556 | (pass-if "max and min" | |
557 | (and (= (max -5 2 4.0 1) 4.0) (= (min -5 2 4.0 1) -5) | |
558 | (= (max 1) 1) (= (min 1) 1))) | |
559 | (pass-if "abs" | |
560 | (and (= (abs 1.0) 1.0) (= (abs -5) 5))) | |
561 | ||
562 | (pass-if "float" | |
563 | (and (= (float 1) 1) (= (float 5.5) 5.5) | |
564 | (floatp (float 1)))) | |
565 | ||
566 | (pass-if-equal "basic arithmetic operators" -8.5 | |
567 | (+ (1+ 0) (1- 0) (- 5.5) (* 2 -2) (- 2 1))) | |
568 | (pass-if "modulo" | |
569 | (= (% 5 3) 2)) | |
570 | ||
571 | (pass-if "floating point rounding" | |
572 | (and (= (ffloor 1.7) 1.0) (= (ffloor -1.2) -2.0) (= (ffloor 1.0) 1.0) | |
573 | (= (fceiling 1.2) 2.0) (= (fceiling -1.7) -1.0) (= (fceiling 1.0) 1.0) | |
574 | (= (ftruncate 1.6) 1.0) (= (ftruncate -1.7) -1.0) | |
575 | (= (fround 1.2) 1.0) (= (fround 1.7) 2.0) (= (fround -1.7) -2.0)))) | |
f614ca12 DK |
576 | |
577 | (with-test-prefix/compile "List Built-Ins" | |
578 | ||
16254e5a | 579 | (pass-if "consp and atom" |
f614ca12 DK |
580 | (and (consp '(1 2 3)) (consp '(1 2 . 3)) (consp '(a . b)) |
581 | (not (consp '())) (not (consp 1)) (not (consp "abc")) | |
16254e5a BT |
582 | (atom 'a) (atom '()) (atom -1.5) (atom "abc") |
583 | (not (atom '(1 . 2))) (not (atom '(1))))) | |
f614ca12 DK |
584 | (pass-if "listp and nlistp" |
585 | (and (listp '(1 2 3)) (listp '(1)) (listp '()) (listp '(1 . 2)) | |
586 | (not (listp 'a)) (not (listp 42)) (nlistp 42) | |
587 | (not (nlistp '())) (not (nlistp '(1 2 3))) (not (nlistp '(1 . 2))))) | |
588 | (pass-if "null" | |
589 | (and (null '()) (not (null 1)) (not (null '(1 2))) (not (null '(1 . 2))))) | |
590 | ||
591 | (pass-if "car and cdr" | |
592 | (and (equal (car '(1 2 3)) 1) (equal (cdr '(1 2 3)) '(2 3)) | |
593 | (equal (car '()) nil) (equal (cdr '()) nil) | |
594 | (equal (car '(1 . 2)) 1) (equal (cdr '(1 . 2)) 2) | |
595 | (null (cdr '(1))))) | |
596 | (pass-if "car-safe and cdr-safe" | |
597 | (and (equal (car-safe '(1 2)) 1) (equal (cdr-safe '(1 2)) '(2)) | |
598 | (equal (car-safe 5) nil) (equal (cdr-safe 5) nil))) | |
599 | ||
f614ca12 DK |
600 | (pass-if "nth and nthcdr" |
601 | (and (equal (nth -5 '(1 2 3)) 1) (equal (nth 3 '(1 2 3)) nil) | |
602 | (equal (nth 0 '(1 2 3)) 1) (equal (nth 2 '(1 2 3)) 3) | |
603 | (equal (nthcdr -5 '(1 2 3)) '(1 2 3)) | |
604 | (equal (nthcdr 4 '(1 2 3)) nil) | |
605 | (equal (nthcdr 1 '(1 2 3)) '(2 3)) | |
606 | (equal (nthcdr 2 '(1 2 3)) '(3)))) | |
607 | ||
c2c7c277 DK |
608 | (pass-if "length" |
609 | (and (= (length '()) 0) | |
610 | (= (length '(1 2 3 4 5)) 5) | |
611 | (= (length '(1 2 (3 4 (5)) 6)) 4))) | |
612 | ||
f614ca12 DK |
613 | (pass-if "cons, list and make-list" |
614 | (and (equal (cons 1 2) '(1 . 2)) (equal (cons 1 '(2 3)) '(1 2 3)) | |
615 | (equal (cons 1 '()) '(1)) | |
616 | (equal (list 'a) '(a)) (equal (list) '()) (equal (list 1 2) '(1 2)) | |
617 | (equal (make-list 3 42) '(42 42 42)) | |
618 | (equal (make-list 0 1) '()))) | |
619 | (pass-if "append" | |
620 | (and (equal (append '(1 2) '(3 4) '(5)) '(1 2 3 4 5)) | |
621 | (equal (append '(1 2) 3) '(1 2 . 3)))) | |
622 | (pass-if "reverse" | |
623 | (and (equal (reverse '(5 4 3 2 1)) '(1 2 3 4 5)) | |
624 | (equal (reverse '()) '()))) | |
f614ca12 DK |
625 | (pass-if "setcar and setcdr" |
626 | (progn (setq pair '(1 . 2)) | |
627 | (setq copy pair) | |
628 | (setq a (setcar copy 3)) | |
629 | (setq b (setcdr copy 4)) | |
630 | (and (= a 3) (= b 4) | |
631 | (equal pair '(3 . 4)))))) |