Implemented some important list built-ins.
[bpt/guile.git] / test-suite / tests / elisp-compiler.test
1 ;;;; elisp-compiler.test --- Test the compiler for Elisp.
2 ;;;;
3 ;;;; Copyright (C) 2009 Free Software Foundation, Inc.
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
29 (syntax-rules (pass-if pass-if-exception)
30 ((_ (pass-if test-name exp))
31 (pass-if test-name (compile 'exp #:from 'elisp #:to 'value)))
32 ((_ (pass-if-equal test-name result exp))
33 (pass-if test-name (equal? result
34 (compile 'exp #:from 'elisp #:to 'value))))
35 ((_ (pass-if-exception test-name exc exp))
36 (pass-if-exception test-name exc
37 (compile 'exp #:from 'elisp #:to 'value)))))
38
39 (define-syntax with-test-prefix/compile
40 (syntax-rules ()
41 ((_ section-name exp ...)
42 (with-test-prefix section-name (compile-test exp) ...))))
43
44
45 ; Test control structures.
46 ; ========================
47
48 (with-test-prefix/compile "Sequencing"
49
50 (pass-if-equal "progn" 1
51 (progn (setq a 0)
52 (setq a (1+ a))
53 a)))
54
55 (with-test-prefix/compile "Conditionals"
56
57 (pass-if-equal "succeeding if" 1
58 (if t 1 2))
59 (pass-if "failing if"
60 (and (= (if nil
61 1
62 (setq a 2) (setq a (1+ a)) a)
63 3)
64 (equal (if nil 1) nil)))
65
66 (pass-if-equal "failing when" nil-value
67 (when nil 1 2 3))
68 (pass-if-equal "succeeding when" 42
69 (progn (setq a 0)
70 (when t (setq a 42) a)))
71
72 (pass-if-equal "failing unless" nil-value
73 (unless t 1 2 3))
74 (pass-if-equal "succeeding unless" 42
75 (progn (setq a 0)
76 (unless nil (setq a 42) a)))
77
78 (pass-if-equal "empty cond" nil-value
79 (cond))
80 (pass-if-equal "all failing cond" nil-value
81 (cond (nil) (nil)))
82 (pass-if-equal "only condition" 5
83 (cond (nil) (5)))
84 (pass-if-equal "succeeding cond value" 42
85 (cond (nil) (t 42) (t 0)))
86 (pass-if-equal "succeeding cond side-effect" 42
87 (progn (setq a 0)
88 (cond (nil) (t (setq a 42) 1) (t (setq a 0)))
89 a)))
90
91 (with-test-prefix/compile "Combining Conditions"
92
93 (pass-if-equal "empty and" t-value (and))
94 (pass-if-equal "failing and" nil-value (and 1 2 nil 3))
95 (pass-if-equal "succeeding and" 3 (and 1 2 3))
96
97 (pass-if-equal "empty or" nil-value (or))
98 (pass-if-equal "failing or" nil-value (or nil nil nil))
99 (pass-if-equal "succeeding or" 1 (or nil 1 nil 2 nil 3))
100
101 (pass-if-equal "not true" nil-value (not 1))
102 (pass-if-equal "not false" t-value (not nil)))
103
104 (with-test-prefix/compile "Iteration"
105
106 (pass-if-equal "failing while" 0
107 (progn (setq a 0)
108 (while nil (setq a 1))
109 a))
110 (pass-if-equal "running while" 120
111 (progn (setq prod 1
112 i 1)
113 (while (<= i 5)
114 (setq prod (* i prod))
115 (setq i (1+ i)))
116 prod))
117
118 (pass-if "dotimes"
119 (progn (setq a 0)
120 (setq count 100)
121 (setq b (dotimes (i count)
122 (setq j (1+ i))
123 (setq a (+ a j))))
124 (setq c (dotimes (i 10 42) nil))
125 (and (= a 5050) (equal b nil) (= c 42)))))
126
127
128 ; Test handling of variables.
129 ; ===========================
130
131 (with-test-prefix/compile "Variable Setting/Referencing"
132
133 ; TODO: Check for variable-void error
134
135 (pass-if-equal "setq and reference" 6
136 (progn (setq a 1 b 2 c 3)
137 (+ a b c)))
138
139 (pass-if-equal "setq value" 2
140 (progn (setq a 1 b 2))))
141
142 (with-test-prefix/compile "Let and Let*"
143
144 (pass-if-equal "let without value" nil-value
145 (let (a (b 5)) a))
146 (pass-if-equal "basic let" 0
147 (progn (setq a 0)
148 (let ((a 1)
149 (b a))
150 b)))
151 (pass-if-equal "let*" 1
152 (progn (setq a 0)
153 (let* ((a 1)
154 (b a))
155 b)))
156
157 (pass-if "local scope"
158 (progn (setq a 0)
159 (setq b (let (a)
160 (setq a 1)
161 a))
162 (and (= a 0)
163 (= b 1)))))
164
165 (with-test-prefix/compile "defconst and defvar"
166
167 (pass-if-equal "defconst without docstring" 3.141
168 (progn (setq pi 3)
169 (defconst pi 3.141)
170 pi))
171 (pass-if-equal "defconst value" 'pi
172 (defconst pi 3.141 "Pi"))
173
174 (pass-if-equal "defvar without value" 42
175 (progn (setq a 42)
176 (defvar a)
177 a))
178 (pass-if-equal "defvar on already defined variable" 42
179 (progn (setq a 42)
180 (defvar a 1 "Some docstring is also ok")
181 a))
182 ; FIXME: makunbound a!
183 (pass-if-equal "defvar on undefined variable" 1
184 (progn (defvar a 1)
185 a))
186 (pass-if-equal "defvar value" 'a
187 (defvar a)))
188
189
190 ; Functions and lambda expressions.
191 ; =================================
192
193 (with-test-prefix/compile "Lambda Expressions"
194
195 (pass-if-equal "required arguments" 3
196 ((lambda (a b c) c) 1 2 3))
197
198 (pass-if-equal "optional argument" 3
199 ((function (lambda (a &optional b c) c)) 1 2 3))
200 (pass-if-equal "optional missing" nil-value
201 ((lambda (&optional a) a)))
202
203 (pass-if-equal "rest argument" '(3 4 5)
204 ((lambda (a b &rest c) c) 1 2 3 4 5))
205 (pass-if-equal "rest missing" nil-value
206 ((lambda (a b &rest c) c) 1 2)))
207
208 (with-test-prefix/compile "Function Definitions"
209
210 (pass-if-equal "defun" 3
211 (progn (defun test (a b) (+ a b))
212 (test 1 2)))
213 (pass-if-equal "defun value" 'test
214 (defun test (a b) (+ a b))))
215
216 (with-test-prefix/compile "Calling Functions"
217
218 (pass-if-equal "recursion" 120
219 (progn (defun factorial (n prod)
220 (if (zerop n)
221 prod
222 (factorial (1- n) (* prod n))))
223 (factorial 5 1)))
224
225 (pass-if "dynamic scoping"
226 (progn (setq a 0)
227 (defun foo ()
228 (setq a (1+ a))
229 a)
230 (defun bar (a)
231 (foo))
232 (and (= 43 (bar 42))
233 (zerop a)))))
234
235
236 ; Quoting and Backquotation.
237 ; ==========================
238
239 (with-test-prefix/compile "Quotation"
240
241 (pass-if "quote"
242 (and (equal '42 42) (equal '"abc" "abc")
243 (equal '(1 2 (3 (4) x)) '(1 2 (3 (4) x)))
244 (not (equal '(1 2 (3 4 (x))) '(1 2 3 4 x)))
245 (equal '(1 2 . 3) '(1 2 . 3))))
246
247 (pass-if "simple backquote"
248 (and (equal (\` 42) 42)
249 (equal (\` (1 (a))) '(1 (a)))
250 (equal (\` (1 . 2)) '(1 . 2))))
251 (pass-if "unquote"
252 (progn (setq a 42 l '(18 12))
253 (and (equal (\` (\, a)) 42)
254 (equal (\` (1 a ((\, l)) . (\, a))) '(1 a ((18 12)) . 42)))))
255 (pass-if "unquote splicing"
256 (progn (setq l '(18 12) empty '())
257 (and (equal (\` (\,@ l)) '(18 12))
258 (equal (\` (l 2 (3 (\,@ l)) ((\,@ l)) (\,@ l)))
259 '(l 2 (3 18 12) (18 12) 18 12))
260 (equal (\` (1 2 (\,@ empty) 3)) '(1 2 3))))))
261
262
263
264 ; Macros.
265 ; =======
266
267 (with-test-prefix/compile "Macros"
268
269 (pass-if-equal "defmacro value" 'magic-number
270 (defmacro magic-number () 42))
271
272 (pass-if-equal "macro expansion" 1
273 (progn (defmacro take-first (a b) a)
274 (take-first 1 (/ 1 0)))))
275
276
277 ; Test the built-ins.
278 ; ===================
279
280 (with-test-prefix/compile "Equivalence Predicates"
281
282 (pass-if "equal"
283 (and (equal 2 2) (not (equal 1 2))
284 (equal "abc" "abc") (not (equal "abc" "ABC"))
285 (equal 'abc 'abc) (not (equal 'abc 'def))
286 (equal '(1 2 (3 4) 5) '(1 2 (3 4) 5))
287 (not (equal '(1 2 3 4 5) '(1 2 (3 4) 5)))))
288
289 (pass-if "eq"
290 (progn (setq some-list '(1 2))
291 (setq some-string "abc")
292 (and (eq 2 2) (not (eq 1 2))
293 (eq 'abc 'abc) (not (eq 'abc 'def))
294 (eq some-string some-string) (not (eq some-string "abc"))
295 (eq some-list some-list) (not (eq some-list '(1 2)))))))
296
297 (with-test-prefix/compile "Number Built-Ins"
298
299 (pass-if "floatp"
300 (and (floatp 1.0) (not (floatp 1)) (not (floatp 'a))))
301 (pass-if "integerp"
302 (and (integerp 42) (integerp -2) (not (integerp 1.0))))
303 (pass-if "numberp"
304 (and (numberp 1.0) (numberp -2) (not (numberp 'a))))
305 (pass-if "wholenump"
306 (and (wholenump 0) (not (wholenump -2)) (not (wholenump 1.0))))
307 (pass-if "zerop"
308 (and (zerop 0) (zerop 0.0) (not (zerop 1))))
309
310 (pass-if "comparisons"
311 (and (= 1 1.0) (/= 0 1)
312 (< 1 2) (> 2 1) (>= 1 1) (<= 1 1)
313 (not (< 1 1)) (not (<= 2 1))))
314
315 (pass-if "max and min"
316 (and (= (max -5 2 4.0 1) 4.0) (= (min -5 2 4.0 1) -5)
317 (= (max 1) 1) (= (min 1) 1)))
318 (pass-if "abs"
319 (and (= (abs 1.0) 1.0) (= (abs -5) 5)))
320
321 (pass-if "float"
322 (and (= (float 1) 1) (= (float 5.5) 5.5)
323 (floatp (float 1))))
324
325 (pass-if-equal "basic arithmetic operators" -8.5
326 (+ (1+ 0) (1- 0) (- 5.5) (* 2 -2) (- 2 1)))
327 (pass-if "modulo"
328 (= (% 5 3) 2))
329
330 (pass-if "floating point rounding"
331 (and (= (ffloor 1.7) 1.0) (= (ffloor -1.2) -2.0) (= (ffloor 1.0) 1.0)
332 (= (fceiling 1.2) 2.0) (= (fceiling -1.7) -1.0) (= (fceiling 1.0) 1.0)
333 (= (ftruncate 1.6) 1.0) (= (ftruncate -1.7) -1.0)
334 (= (fround 1.2) 1.0) (= (fround 1.7) 2.0) (= (fround -1.7) -2.0))))
335
336 (with-test-prefix/compile "List Built-Ins"
337
338 (pass-if "consp and atomp"
339 (and (consp '(1 2 3)) (consp '(1 2 . 3)) (consp '(a . b))
340 (not (consp '())) (not (consp 1)) (not (consp "abc"))
341 (atomp 'a) (atomp '()) (atomp -1.5) (atomp "abc")
342 (not (atomp '(1 . 2))) (not (atomp '(1)))))
343 (pass-if "listp and nlistp"
344 (and (listp '(1 2 3)) (listp '(1)) (listp '()) (listp '(1 . 2))
345 (not (listp 'a)) (not (listp 42)) (nlistp 42)
346 (not (nlistp '())) (not (nlistp '(1 2 3))) (not (nlistp '(1 . 2)))))
347 (pass-if "null"
348 (and (null '()) (not (null 1)) (not (null '(1 2))) (not (null '(1 . 2)))))
349
350 (pass-if "car and cdr"
351 (and (equal (car '(1 2 3)) 1) (equal (cdr '(1 2 3)) '(2 3))
352 (equal (car '()) nil) (equal (cdr '()) nil)
353 (equal (car '(1 . 2)) 1) (equal (cdr '(1 . 2)) 2)
354 (null (cdr '(1)))))
355 (pass-if "car-safe and cdr-safe"
356 (and (equal (car-safe '(1 2)) 1) (equal (cdr-safe '(1 2)) '(2))
357 (equal (car-safe 5) nil) (equal (cdr-safe 5) nil)))
358
359 (pass-if "pop"
360 (progn (setq mylist '(a b c))
361 (setq value (pop mylist))
362 (and (equal value 'a)
363 (equal mylist '(b c)))))
364 (pass-if-equal "push" '(a b c)
365 (progn (setq mylist '(b c))
366 (push 'a mylist)))
367
368 (pass-if "nth and nthcdr"
369 (and (equal (nth -5 '(1 2 3)) 1) (equal (nth 3 '(1 2 3)) nil)
370 (equal (nth 0 '(1 2 3)) 1) (equal (nth 2 '(1 2 3)) 3)
371 (equal (nthcdr -5 '(1 2 3)) '(1 2 3))
372 (equal (nthcdr 4 '(1 2 3)) nil)
373 (equal (nthcdr 1 '(1 2 3)) '(2 3))
374 (equal (nthcdr 2 '(1 2 3)) '(3))))
375
376 (pass-if "cons, list and make-list"
377 (and (equal (cons 1 2) '(1 . 2)) (equal (cons 1 '(2 3)) '(1 2 3))
378 (equal (cons 1 '()) '(1))
379 (equal (list 'a) '(a)) (equal (list) '()) (equal (list 1 2) '(1 2))
380 (equal (make-list 3 42) '(42 42 42))
381 (equal (make-list 0 1) '())))
382 (pass-if "append"
383 (and (equal (append '(1 2) '(3 4) '(5)) '(1 2 3 4 5))
384 (equal (append '(1 2) 3) '(1 2 . 3))))
385 (pass-if "reverse"
386 (and (equal (reverse '(5 4 3 2 1)) '(1 2 3 4 5))
387 (equal (reverse '()) '())))
388 (pass-if "copy-tree"
389 (progn (setq mylist '(1 2 (3 4)))
390 (and (not (eq mylist (copy-tree mylist)))
391 (equal mylist (copy-tree mylist)))))
392
393 (pass-if "number-sequence"
394 (and (equal (number-sequence 5) '(5))
395 (equal (number-sequence 5 9) '(5 6 7 8 9))
396 (equal (number-sequence 5 9 3) '(5 8))
397 (equal (number-sequence 5 1 -2) '(5 3 1))
398 (equal (number-sequence 5 8 -1) '())
399 (equal (number-sequence 5 1) '())
400 (equal (number-sequence 5 5 0) '(5))))
401
402 (pass-if "setcar and setcdr"
403 (progn (setq pair '(1 . 2))
404 (setq copy pair)
405 (setq a (setcar copy 3))
406 (setq b (setcdr copy 4))
407 (and (= a 3) (= b 4)
408 (equal pair '(3 . 4))))))