Commit | Line | Data |
---|---|---|
f764e6d1 MG |
1 | ;;;; srfi-9.test --- Test suite for Guile's SRFI-9 functions. -*- scheme -*- |
2 | ;;;; Martin Grabmueller, 2001-05-10 | |
3 | ;;;; | |
361553b4 MW |
4 | ;;;; Copyright (C) 2001, 2006, 2007, 2010, 2011, 2012, |
5 | ;;;; 2013 Free Software Foundation, Inc. | |
f764e6d1 | 6 | ;;;; |
53befeb7 NJ |
7 | ;;;; This library is free software; you can redistribute it and/or |
8 | ;;;; modify it under the terms of the GNU Lesser General Public | |
9 | ;;;; License as published by the Free Software Foundation; either | |
10 | ;;;; version 3 of the License, or (at your option) any later version. | |
f764e6d1 | 11 | ;;;; |
53befeb7 | 12 | ;;;; This library is distributed in the hope that it will be useful, |
f764e6d1 | 13 | ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
53befeb7 NJ |
14 | ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | ;;;; Lesser General Public License for more details. | |
f764e6d1 | 16 | ;;;; |
53befeb7 NJ |
17 | ;;;; You should have received a copy of the GNU Lesser General Public |
18 | ;;;; License along with this library; if not, write to the Free Software | |
19 | ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
f764e6d1 | 20 | |
8ab3d8a0 KR |
21 | (define-module (test-suite test-numbers) |
22 | #:use-module (test-suite lib) | |
30a700c8 | 23 | #:use-module ((system base compile) #:select (compile)) |
d9e36897 MW |
24 | #:use-module (srfi srfi-26) |
25 | #:use-module (srfi srfi-9) | |
26 | #:use-module (srfi srfi-9 gnu)) | |
8ab3d8a0 KR |
27 | |
28 | ||
c4a8200f AR |
29 | (define-record-type :qux (make-qux) qux?) |
30 | ||
d9e36897 MW |
31 | (define-record-type :foo (make-foo x) foo? |
32 | (x foo-x) | |
33 | (y foo-y set-foo-y!) | |
34 | (z foo-z set-foo-z!)) | |
f764e6d1 | 35 | |
d9e36897 MW |
36 | (define-record-type :bar (make-bar i j) bar? |
37 | (i bar-i) | |
38 | (j bar-j set-bar-j!)) | |
8ab3d8a0 | 39 | |
f764e6d1 | 40 | (define f (make-foo 1)) |
d9e36897 | 41 | (set-foo-y! f 2) |
f764e6d1 | 42 | |
8ab3d8a0 KR |
43 | (define b (make-bar 123 456)) |
44 | ||
361553b4 MW |
45 | (define exception:syntax-error-wrong-num-args |
46 | (cons 'syntax-error "Wrong number of arguments")) | |
47 | ||
8ab3d8a0 KR |
48 | (with-test-prefix "constructor" |
49 | ||
30a700c8 LC |
50 | ;; Constructors are defined using `define-integrable', meaning that direct |
51 | ;; calls as in `(make-foo)' lead to a compile-time psyntax error, hence the | |
52 | ;; distinction below. | |
53 | ||
361553b4 | 54 | (pass-if-exception "foo 0 args (inline)" exception:syntax-error-wrong-num-args |
30a700c8 | 55 | (compile '(make-foo) #:env (current-module))) |
361553b4 | 56 | (pass-if-exception "foo 2 args (inline)" exception:syntax-error-wrong-num-args |
30a700c8 LC |
57 | (compile '(make-foo 1 2) #:env (current-module))) |
58 | ||
8ab3d8a0 | 59 | (pass-if-exception "foo 0 args" exception:wrong-num-args |
30a700c8 LC |
60 | (let ((make-foo make-foo)) |
61 | (make-foo))) | |
8ab3d8a0 | 62 | (pass-if-exception "foo 2 args" exception:wrong-num-args |
30a700c8 LC |
63 | (let ((make-foo make-foo)) |
64 | (make-foo 1 2)))) | |
8ab3d8a0 KR |
65 | |
66 | (with-test-prefix "predicate" | |
f764e6d1 | 67 | |
8ab3d8a0 | 68 | (pass-if "pass" |
f764e6d1 | 69 | (foo? f)) |
8ab3d8a0 KR |
70 | (pass-if "fail wrong record type" |
71 | (eq? #f (foo? b))) | |
72 | (pass-if "fail number" | |
73 | (eq? #f (foo? 123)))) | |
f764e6d1 | 74 | |
d9e36897 | 75 | (with-test-prefix "getter" |
f764e6d1 | 76 | |
d9e36897 MW |
77 | (pass-if "foo-x" |
78 | (= 1 (foo-x f))) | |
79 | (pass-if "foo-y" | |
80 | (= 2 (foo-y f))) | |
f764e6d1 | 81 | |
d9e36897 MW |
82 | (pass-if-exception "foo-x on number" exception:wrong-type-arg |
83 | (foo-x 999)) | |
84 | (pass-if-exception "foo-y on number" exception:wrong-type-arg | |
85 | (foo-y 999)) | |
8ab3d8a0 KR |
86 | |
87 | ;; prior to guile 1.6.9 and 1.8.1 this wan't enforced | |
d9e36897 MW |
88 | (pass-if-exception "foo-x on bar" exception:wrong-type-arg |
89 | (foo-x b)) | |
90 | (pass-if-exception "foo-y on bar" exception:wrong-type-arg | |
91 | (foo-y b))) | |
8ab3d8a0 | 92 | |
d9e36897 | 93 | (with-test-prefix "setter" |
8ab3d8a0 | 94 | |
d9e36897 MW |
95 | (pass-if "set-foo-y!" |
96 | (set-foo-y! f #t) | |
97 | (eq? #t (foo-y f))) | |
8ab3d8a0 | 98 | |
d9e36897 MW |
99 | (pass-if-exception "set-foo-y! on number" exception:wrong-type-arg |
100 | (set-foo-y! 999 #t)) | |
8ab3d8a0 KR |
101 | |
102 | ;; prior to guile 1.6.9 and 1.8.1 this wan't enforced | |
d9e36897 MW |
103 | (pass-if-exception "set-foo-y! on bar" exception:wrong-type-arg |
104 | (set-foo-y! b 99))) | |
105 | ||
106 | (with-test-prefix "functional setters" | |
107 | ||
108 | (pass-if "set-field" | |
109 | (let ((s (make-foo (make-bar 1 2)))) | |
3d01c19a | 110 | (and (equal? (set-field s (foo-x bar-j) 3) |
d9e36897 | 111 | (make-foo (make-bar 1 3))) |
3d01c19a | 112 | (equal? (set-field s (foo-z) 'bar) |
d9e36897 MW |
113 | (let ((s2 (make-foo (make-bar 1 2)))) |
114 | (set-foo-z! s2 'bar) | |
115 | s2)) | |
116 | (equal? s (make-foo (make-bar 1 2)))))) | |
117 | ||
118 | (pass-if-exception "set-field on wrong struct type" exception:wrong-type-arg | |
119 | (let ((s (make-bar (make-foo 5) 2))) | |
3d01c19a | 120 | (set-field s (foo-x bar-j) 3))) |
d9e36897 MW |
121 | |
122 | (pass-if-exception "set-field on number" exception:wrong-type-arg | |
3d01c19a | 123 | (set-field 4 (foo-x bar-j) 3)) |
d9e36897 | 124 | |
ce650853 MW |
125 | (pass-if-equal "set-field with unknown first getter" |
126 | '(syntax-error set-fields "unknown getter" | |
3d01c19a | 127 | (set-field s (blah) 3) |
ce650853 | 128 | blah) |
d9e36897 MW |
129 | (catch 'syntax-error |
130 | (lambda () | |
131 | (compile '(let ((s (make-bar (make-foo 5) 2))) | |
3d01c19a | 132 | (set-field s (blah) 3)) |
d9e36897 MW |
133 | #:env (current-module)) |
134 | #f) | |
135 | (lambda (key whom what src form subform) | |
ce650853 | 136 | (list key whom what form subform)))) |
d9e36897 | 137 | |
ce650853 MW |
138 | (pass-if-equal "set-field with unknown second getter" |
139 | '(syntax-error set-fields "unknown getter" | |
3d01c19a | 140 | (set-field s (bar-j blah) 3) |
ce650853 | 141 | blah) |
d9e36897 MW |
142 | (catch 'syntax-error |
143 | (lambda () | |
144 | (compile '(let ((s (make-bar (make-foo 5) 2))) | |
3d01c19a | 145 | (set-field s (bar-j blah) 3)) |
d9e36897 MW |
146 | #:env (current-module)) |
147 | #f) | |
148 | (lambda (key whom what src form subform) | |
ce650853 | 149 | (list key whom what form subform)))) |
d9e36897 MW |
150 | |
151 | (pass-if "set-fields" | |
152 | (let ((s (make-foo (make-bar 1 2)))) | |
3d01c19a | 153 | (and (equal? (set-field s (foo-x bar-j) 3) |
d9e36897 MW |
154 | (make-foo (make-bar 1 3))) |
155 | (equal? (set-fields s | |
156 | ((foo-x bar-j) 3) | |
157 | ((foo-z) 'bar)) | |
158 | (let ((s2 (make-foo (make-bar 1 3)))) | |
159 | (set-foo-z! s2 'bar) | |
160 | s2)) | |
161 | (equal? s (make-foo (make-bar 1 2)))))) | |
162 | ||
163 | (pass-if-exception "set-fields on wrong struct type" exception:wrong-type-arg | |
164 | (let ((s (make-bar (make-foo 5) 2))) | |
165 | (set-fields 4 | |
166 | ((foo-x bar-j) 3) | |
167 | ((foo-y) 'bar)))) | |
168 | ||
169 | (pass-if-exception "set-fields on number" exception:wrong-type-arg | |
170 | (set-fields 4 | |
171 | ((foo-x bar-j) 3) | |
172 | ((foo-z) 'bar))) | |
173 | ||
ce650853 MW |
174 | (pass-if-equal "set-fields with unknown first getter" |
175 | '(syntax-error set-fields "unknown getter" | |
176 | (set-fields s ((bar-i foo-x) 1) ((blah) 3)) | |
177 | blah) | |
d9e36897 MW |
178 | (catch 'syntax-error |
179 | (lambda () | |
180 | (compile '(let ((s (make-bar (make-foo 5) 2))) | |
181 | (set-fields s ((bar-i foo-x) 1) ((blah) 3))) | |
182 | #:env (current-module)) | |
183 | #f) | |
184 | (lambda (key whom what src form subform) | |
ce650853 | 185 | (list key whom what form subform)))) |
d9e36897 | 186 | |
ce650853 MW |
187 | (pass-if-equal "set-fields with unknown second getter" |
188 | '(syntax-error set-fields "unknown getter" | |
189 | (set-fields s ((bar-i foo-x) 1) ((blah) 3)) | |
190 | blah) | |
d9e36897 MW |
191 | (catch 'syntax-error |
192 | (lambda () | |
193 | (compile '(let ((s (make-bar (make-foo 5) 2))) | |
194 | (set-fields s ((bar-i foo-x) 1) ((blah) 3))) | |
195 | #:env (current-module)) | |
196 | #f) | |
197 | (lambda (key whom what src form subform) | |
ce650853 MW |
198 | (list key whom what form subform)))) |
199 | ||
200 | (pass-if-equal "set-fields with duplicate field path" | |
201 | '(syntax-error set-fields "duplicate field path" | |
202 | (set-fields s | |
203 | ((bar-i foo-x) 1) | |
204 | ((bar-i foo-z) 2) | |
205 | ((bar-i foo-x) 3)) | |
206 | (bar-i foo-x)) | |
d9e36897 MW |
207 | (catch 'syntax-error |
208 | (lambda () | |
209 | (compile '(let ((s (make-bar (make-foo 5) 2))) | |
210 | (set-fields s | |
211 | ((bar-i foo-x) 1) | |
212 | ((bar-i foo-z) 2) | |
213 | ((bar-i foo-x) 3))) | |
214 | #:env (current-module)) | |
215 | #f) | |
216 | (lambda (key whom what src form subform) | |
ce650853 MW |
217 | (list key whom what form subform)))) |
218 | ||
219 | (pass-if-equal "set-fields with one path as a prefix of another" | |
220 | '(syntax-error set-fields | |
221 | "one field path is a prefix of another" | |
222 | (set-fields s | |
223 | ((bar-i foo-x) 1) | |
224 | ((bar-i foo-z) 2) | |
225 | ((bar-i) 3)) | |
226 | (bar-i)) | |
d9e36897 MW |
227 | (catch 'syntax-error |
228 | (lambda () | |
229 | (compile '(let ((s (make-bar (make-foo 5) 2))) | |
230 | (set-fields s | |
231 | ((bar-i foo-x) 1) | |
232 | ((bar-i foo-z) 2) | |
233 | ((bar-i) 3))) | |
234 | #:env (current-module)) | |
235 | #f) | |
236 | (lambda (key whom what src form subform) | |
ce650853 | 237 | (list key whom what form subform))))) |
531c9f1d | 238 | |
b075a6d7 LC |
239 | (with-test-prefix "side-effecting arguments" |
240 | ||
241 | (pass-if "predicate" | |
242 | (let ((x 0)) | |
243 | (and (foo? (begin (set! x (+ x 1)) f)) | |
244 | (= x 1))))) | |
245 | ||
531c9f1d | 246 | (with-test-prefix "non-toplevel" |
b075a6d7 | 247 | |
531c9f1d AR |
248 | (define-record-type :frotz (make-frotz a b) frotz? |
249 | (a frotz-a) (b frotz-b set-frotz-b!)) | |
250 | ||
251 | (pass-if "construction" | |
252 | (let ((frotz (make-frotz 1 2))) | |
253 | (and (= (frotz-a frotz) 1) | |
d9e36897 MW |
254 | (= (frotz-b frotz) 2)))) |
255 | ||
256 | (with-test-prefix "functional setters" | |
257 | (let () | |
258 | (define-record-type foo (make-foo x) foo? | |
259 | (x foo-x) | |
260 | (y foo-y set-foo-y!) | |
261 | (z foo-z set-foo-z!)) | |
262 | ||
263 | (define-record-type :bar (make-bar i j) bar? | |
264 | (i bar-i) | |
265 | (j bar-j set-bar-j!)) | |
266 | ||
267 | (pass-if "set-field" | |
268 | (let ((s (make-foo (make-bar 1 2)))) | |
3d01c19a | 269 | (and (equal? (set-field s (foo-x bar-j) 3) |
d9e36897 | 270 | (make-foo (make-bar 1 3))) |
3d01c19a | 271 | (equal? (set-field s (foo-z) 'bar) |
d9e36897 MW |
272 | (let ((s2 (make-foo (make-bar 1 2)))) |
273 | (set-foo-z! s2 'bar) | |
274 | s2)) | |
275 | (equal? s (make-foo (make-bar 1 2))))))) | |
276 | ||
3d01c19a | 277 | (pass-if "set-fieldss " |
d9e36897 MW |
278 | |
279 | (let ((s (make-foo (make-bar 1 2)))) | |
3d01c19a | 280 | (and (equal? (set-field s (foo-x bar-j) 3) |
d9e36897 MW |
281 | (make-foo (make-bar 1 3))) |
282 | (equal? (set-fields s | |
283 | ((foo-x bar-j) 3) | |
284 | ((foo-z) 'bar)) | |
285 | (let ((s2 (make-foo (make-bar 1 3)))) | |
286 | (set-foo-z! s2 'bar) | |
287 | s2)) | |
288 | (equal? s (make-foo (make-bar 1 2)))))))) | |
289 | ||
290 | \f | |
291 | (define-immutable-record-type :baz | |
292 | (make-baz x y z) | |
293 | baz? | |
294 | (x baz-x set-baz-x) | |
295 | (y baz-y set-baz-y) | |
296 | (z baz-z set-baz-z)) | |
297 | ||
298 | (define-immutable-record-type :address | |
299 | (make-address street city country) | |
300 | address? | |
301 | (street address-street) | |
302 | (city address-city) | |
303 | (country address-country)) | |
304 | ||
305 | (define-immutable-record-type :person | |
306 | (make-person age email address) | |
307 | person? | |
308 | (age person-age) | |
309 | (email person-email) | |
310 | (address person-address)) | |
311 | ||
312 | (with-test-prefix "define-immutable-record-type" | |
313 | ||
314 | (pass-if "get" | |
315 | (let ((b (make-baz 1 2 3))) | |
316 | (and (= (baz-x b) 1) | |
317 | (= (baz-y b) 2) | |
318 | (= (baz-z b) 3)))) | |
319 | ||
320 | (pass-if "get non-inlined" | |
321 | (let ((b (make-baz 1 2 3))) | |
322 | (equal? (map (cute apply <> (list b)) | |
323 | (list baz-x baz-y baz-z)) | |
324 | '(1 2 3)))) | |
325 | ||
326 | (pass-if "set" | |
327 | (let* ((b0 (make-baz 1 2 3)) | |
328 | (b1 (set-baz-x b0 11)) | |
329 | (b2 (set-baz-y b1 22)) | |
330 | (b3 (set-baz-z b2 33))) | |
331 | (and (= (baz-x b0) 1) | |
332 | (= (baz-x b1) 11) (= (baz-x b2) 11) (= (baz-x b3) 11) | |
333 | (= (baz-y b0) 2) (= (baz-y b1) 2) | |
334 | (= (baz-y b2) 22) (= (baz-y b3) 22) | |
335 | (= (baz-z b0) 3) (= (baz-z b1) 3) (= (baz-z b2) 3) | |
336 | (= (baz-z b3) 33)))) | |
337 | ||
338 | (pass-if "set non-inlined" | |
339 | (let ((set (compose (cut set-baz-x <> 1) | |
340 | (cut set-baz-y <> 2) | |
341 | (cut set-baz-z <> 3)))) | |
342 | (equal? (set (make-baz 0 0 0)) (make-baz 1 2 3)))) | |
343 | ||
344 | (pass-if "set-field" | |
345 | (let ((p (make-person 30 "foo@example.com" | |
346 | (make-address "Foo" "Paris" "France")))) | |
3d01c19a | 347 | (and (equal? (set-field p (person-address address-street) "Bar") |
d9e36897 MW |
348 | (make-person 30 "foo@example.com" |
349 | (make-address "Bar" "Paris" "France"))) | |
3d01c19a | 350 | (equal? (set-field p (person-email) "bar@example.com") |
d9e36897 MW |
351 | (make-person 30 "bar@example.com" |
352 | (make-address "Foo" "Paris" "France"))) | |
353 | (equal? p (make-person 30 "foo@example.com" | |
354 | (make-address "Foo" "Paris" "France")))))) | |
355 | ||
356 | (pass-if "set-fields" | |
357 | (let ((p (make-person 30 "foo@example.com" | |
358 | (make-address "Foo" "Paris" "France")))) | |
359 | (and (equal? (set-fields p | |
360 | ((person-email) "bar@example.com") | |
361 | ((person-address address-country) "Catalonia") | |
362 | ((person-address address-city) "Barcelona")) | |
363 | (make-person 30 "bar@example.com" | |
364 | (make-address "Foo" "Barcelona" "Catalonia"))) | |
365 | (equal? (set-fields p | |
366 | ((person-email) "bar@example.com") | |
367 | ((person-age) 20)) | |
368 | (make-person 20 "bar@example.com" | |
369 | (make-address "Foo" "Paris" "France"))) | |
370 | (equal? p (make-person 30 "foo@example.com" | |
371 | (make-address "Foo" "Paris" "France")))))) | |
372 | ||
373 | (with-test-prefix "non-toplevel" | |
374 | ||
375 | (pass-if "get" | |
376 | (let () | |
377 | (define-immutable-record-type bar | |
378 | (make-bar x y z) | |
379 | bar? | |
380 | (x bar-x) | |
381 | (y bar-y) | |
382 | (z bar-z set-bar-z)) | |
383 | ||
384 | (let ((b (make-bar 1 2 3))) | |
385 | (and (= (bar-x b) 1) | |
386 | (= (bar-y b) 2) | |
387 | (= (bar-z b) 3))))) | |
388 | ||
389 | (pass-if "get non-inlined" | |
390 | (let () | |
391 | (define-immutable-record-type bar | |
392 | (make-bar x y z) | |
393 | bar? | |
394 | (x bar-x) | |
395 | (y bar-y) | |
396 | (z bar-z set-bar-z)) | |
397 | ||
398 | (let ((b (make-bar 1 2 3))) | |
399 | (equal? (map (cute apply <> (list b)) | |
400 | (list bar-x bar-y bar-z)) | |
401 | '(1 2 3))))) | |
402 | ||
403 | (pass-if "set" | |
404 | (let () | |
405 | (define-immutable-record-type bar | |
406 | (make-bar x y z) | |
407 | bar? | |
408 | (x bar-x set-bar-x) | |
409 | (y bar-y set-bar-y) | |
410 | (z bar-z set-bar-z)) | |
411 | ||
412 | (let* ((b0 (make-bar 1 2 3)) | |
413 | (b1 (set-bar-x b0 11)) | |
414 | (b2 (set-bar-y b1 22)) | |
415 | (b3 (set-bar-z b2 33))) | |
416 | (and (= (bar-x b0) 1) | |
417 | (= (bar-x b1) 11) (= (bar-x b2) 11) (= (bar-x b3) 11) | |
418 | (= (bar-y b0) 2) (= (bar-y b1) 2) | |
419 | (= (bar-y b2) 22) (= (bar-y b3) 22) | |
420 | (= (bar-z b0) 3) (= (bar-z b1) 3) (= (bar-z b2) 3) | |
421 | (= (bar-z b3) 33))))) | |
422 | ||
423 | (pass-if "set non-inlined" | |
424 | (let () | |
425 | (define-immutable-record-type bar | |
426 | (make-bar x y z) | |
427 | bar? | |
428 | (x bar-x set-bar-x) | |
429 | (y bar-y set-bar-y) | |
430 | (z bar-z set-bar-z)) | |
431 | ||
432 | (let ((set (compose (cut set-bar-x <> 1) | |
433 | (cut set-bar-y <> 2) | |
434 | (cut set-bar-z <> 3)))) | |
435 | (equal? (set (make-bar 0 0 0)) (make-bar 1 2 3))))) | |
436 | ||
437 | (pass-if "set-field" | |
438 | (let () | |
439 | (define-immutable-record-type address | |
440 | (make-address street city country) | |
441 | address? | |
442 | (street address-street) | |
443 | (city address-city) | |
444 | (country address-country)) | |
445 | ||
446 | (define-immutable-record-type :person | |
447 | (make-person age email address) | |
448 | person? | |
449 | (age person-age) | |
450 | (email person-email) | |
451 | (address person-address)) | |
452 | ||
453 | (let ((p (make-person 30 "foo@example.com" | |
454 | (make-address "Foo" "Paris" "France")))) | |
3d01c19a | 455 | (and (equal? (set-field p (person-address address-street) "Bar") |
d9e36897 MW |
456 | (make-person 30 "foo@example.com" |
457 | (make-address "Bar" "Paris" "France"))) | |
3d01c19a | 458 | (equal? (set-field p (person-email) "bar@example.com") |
d9e36897 MW |
459 | (make-person 30 "bar@example.com" |
460 | (make-address "Foo" "Paris" "France"))) | |
461 | (equal? p (make-person 30 "foo@example.com" | |
462 | (make-address "Foo" "Paris" "France"))))))) | |
463 | ||
464 | (pass-if "set-fields" | |
465 | (let () | |
466 | (define-immutable-record-type address | |
467 | (make-address street city country) | |
468 | address? | |
469 | (street address-street) | |
470 | (city address-city) | |
471 | (country address-country)) | |
472 | ||
473 | (define-immutable-record-type :person | |
474 | (make-person age email address) | |
475 | person? | |
476 | (age person-age) | |
477 | (email person-email) | |
478 | (address person-address)) | |
479 | ||
480 | (let ((p (make-person 30 "foo@example.com" | |
481 | (make-address "Foo" "Paris" "France")))) | |
482 | (and (equal? (set-fields p | |
483 | ((person-email) "bar@example.com") | |
484 | ((person-address address-country) "Catalonia") | |
485 | ((person-address address-city) "Barcelona")) | |
486 | (make-person 30 "bar@example.com" | |
487 | (make-address "Foo" "Barcelona" "Catalonia"))) | |
488 | (equal? (set-fields p | |
489 | ((person-email) "bar@example.com") | |
490 | ((person-age) 20)) | |
491 | (make-person 20 "bar@example.com" | |
492 | (make-address "Foo" "Paris" "France"))) | |
493 | (equal? p (make-person 30 "foo@example.com" | |
494 | (make-address "Foo" "Paris" "France"))))))) | |
495 | ||
ce650853 MW |
496 | (pass-if-equal "set-fields with unknown first getter" |
497 | '(syntax-error set-fields "unknown getter" | |
498 | (set-fields s ((bar-i foo-x) 1) ((blah) 3)) | |
499 | blah) | |
dfba1025 MW |
500 | (catch 'syntax-error |
501 | (lambda () | |
502 | (compile '(let () | |
503 | (define-immutable-record-type foo | |
504 | (make-foo x) | |
505 | foo? | |
506 | (x foo-x) | |
507 | (y foo-y set-foo-y) | |
508 | (z foo-z set-foo-z)) | |
509 | ||
510 | (define-immutable-record-type :bar | |
511 | (make-bar i j) | |
512 | bar? | |
513 | (i bar-i) | |
514 | (j bar-j set-bar-j)) | |
515 | ||
516 | (let ((s (make-bar (make-foo 5) 2))) | |
517 | (set-fields s ((bar-i foo-x) 1) ((blah) 3)))) | |
518 | #:env (current-module)) | |
519 | #f) | |
520 | (lambda (key whom what src form subform) | |
521 | (list key whom what form subform)))) | |
ce650853 MW |
522 | |
523 | (pass-if-equal "set-fields with unknown second getter" | |
524 | '(syntax-error set-fields "unknown getter" | |
525 | (set-fields s ((bar-i foo-x) 1) ((blah) 3)) | |
526 | blah) | |
dfba1025 MW |
527 | (catch 'syntax-error |
528 | (lambda () | |
529 | (compile '(let () | |
530 | (define-immutable-record-type foo | |
531 | (make-foo x) | |
532 | foo? | |
533 | (x foo-x) | |
534 | (y foo-y set-foo-y) | |
535 | (z foo-z set-foo-z)) | |
536 | ||
537 | (define-immutable-record-type :bar | |
538 | (make-bar i j) | |
539 | bar? | |
540 | (i bar-i) | |
541 | (j bar-j set-bar-j)) | |
542 | ||
543 | (let ((s (make-bar (make-foo 5) 2))) | |
544 | (set-fields s ((bar-i foo-x) 1) ((blah) 3)))) | |
545 | #:env (current-module)) | |
546 | #f) | |
547 | (lambda (key whom what src form subform) | |
548 | (list key whom what form subform)))) | |
ce650853 MW |
549 | |
550 | (pass-if-equal "set-fields with duplicate field path" | |
551 | '(syntax-error set-fields "duplicate field path" | |
552 | (set-fields s | |
553 | ((bar-i foo-x) 1) | |
554 | ((bar-i foo-z) 2) | |
555 | ((bar-i foo-x) 3)) | |
556 | (bar-i foo-x)) | |
dfba1025 MW |
557 | (catch 'syntax-error |
558 | (lambda () | |
559 | (compile '(let () | |
560 | (define-immutable-record-type foo | |
561 | (make-foo x) | |
562 | foo? | |
563 | (x foo-x) | |
564 | (y foo-y set-foo-y) | |
565 | (z foo-z set-foo-z)) | |
566 | ||
567 | (define-immutable-record-type :bar | |
568 | (make-bar i j) | |
569 | bar? | |
570 | (i bar-i) | |
571 | (j bar-j set-bar-j)) | |
572 | ||
573 | (let ((s (make-bar (make-foo 5) 2))) | |
ce650853 MW |
574 | (set-fields s |
575 | ((bar-i foo-x) 1) | |
576 | ((bar-i foo-z) 2) | |
dfba1025 MW |
577 | ((bar-i foo-x) 3)))) |
578 | #:env (current-module)) | |
579 | #f) | |
580 | (lambda (key whom what src form subform) | |
581 | (list key whom what form subform)))) | |
ce650853 MW |
582 | |
583 | (pass-if-equal "set-fields with one path as a prefix of another" | |
584 | '(syntax-error set-fields | |
585 | "one field path is a prefix of another" | |
d9e36897 MW |
586 | (set-fields s |
587 | ((bar-i foo-x) 1) | |
588 | ((bar-i foo-z) 2) | |
ce650853 MW |
589 | ((bar-i) 3)) |
590 | (bar-i)) | |
dfba1025 MW |
591 | (catch 'syntax-error |
592 | (lambda () | |
593 | (compile '(let () | |
594 | (define-immutable-record-type foo | |
595 | (make-foo x) | |
596 | foo? | |
597 | (x foo-x) | |
598 | (y foo-y set-foo-y) | |
599 | (z foo-z set-foo-z)) | |
600 | ||
601 | (define-immutable-record-type :bar | |
602 | (make-bar i j) | |
603 | bar? | |
604 | (i bar-i) | |
605 | (j bar-j set-bar-j)) | |
606 | ||
607 | (let ((s (make-bar (make-foo 5) 2))) | |
ce650853 MW |
608 | (set-fields s |
609 | ((bar-i foo-x) 1) | |
610 | ((bar-i foo-z) 2) | |
dfba1025 MW |
611 | ((bar-i) 3)))) |
612 | #:env (current-module)) | |
92fac8c0 MW |
613 | #f) |
614 | (lambda (key whom what src form subform) | |
615 | (list key whom what form subform)))) | |
616 | ||
617 | (pass-if-equal "incompatible field paths" | |
618 | '(syntax-error set-fields | |
619 | "\ | |
620 | field paths (bar-i bar-j) and (bar-i foo-x) require one object \ | |
b5949983 | 621 | to belong to two different record types (bar and foo)" |
92fac8c0 MW |
622 | (set-fields s |
623 | ((bar-i foo-x) 1) | |
624 | ((bar-i bar-j) 2) | |
625 | ((bar-j) 3)) | |
626 | #f) | |
627 | (catch 'syntax-error | |
628 | (lambda () | |
629 | (compile '(let () | |
630 | (define-immutable-record-type foo | |
631 | (make-foo x) | |
632 | foo? | |
633 | (x foo-x) | |
634 | (y foo-y set-foo-y) | |
635 | (z foo-z set-foo-z)) | |
636 | ||
b5949983 | 637 | (define-immutable-record-type bar |
92fac8c0 MW |
638 | (make-bar i j) |
639 | bar? | |
640 | (i bar-i) | |
641 | (j bar-j set-bar-j)) | |
642 | ||
643 | (let ((s (make-bar (make-foo 5) 2))) | |
644 | (set-fields s | |
645 | ((bar-i foo-x) 1) | |
646 | ((bar-i bar-j) 2) | |
647 | ((bar-j) 3)))) | |
648 | #:env (current-module)) | |
dfba1025 MW |
649 | #f) |
650 | (lambda (key whom what src form subform) | |
651 | (list key whom what form subform)))))) | |
5ef102cc | 652 | |
f31a0762 MW |
653 | \f |
654 | (with-test-prefix "record type definition error reporting" | |
655 | ||
656 | (pass-if-equal "invalid type name" | |
657 | '(syntax-error define-immutable-record-type | |
658 | "expected type name" | |
659 | (define-immutable-record-type | |
660 | (foobar x y) | |
661 | foobar? | |
662 | (x foobar-x) | |
663 | (y foobar-y)) | |
664 | (foobar x y)) | |
665 | (catch 'syntax-error | |
666 | (lambda () | |
667 | (compile '(define-immutable-record-type | |
668 | (foobar x y) | |
669 | foobar? | |
670 | (x foobar-x) | |
671 | (y foobar-y)) | |
672 | #:env (current-module)) | |
673 | #f) | |
674 | (lambda (key whom what src form subform) | |
675 | (list key whom what form subform)))) | |
676 | ||
677 | (pass-if-equal "invalid constructor spec" | |
678 | '(syntax-error define-immutable-record-type | |
679 | "invalid constructor spec" | |
680 | (define-immutable-record-type :foobar | |
681 | (make-foobar x y 3) | |
682 | foobar? | |
683 | (x foobar-x) | |
684 | (y foobar-y)) | |
685 | (make-foobar x y 3)) | |
686 | (catch 'syntax-error | |
687 | (lambda () | |
688 | (compile '(define-immutable-record-type :foobar | |
689 | (make-foobar x y 3) | |
690 | foobar? | |
691 | (x foobar-x) | |
692 | (y foobar-y)) | |
693 | #:env (current-module)) | |
694 | #f) | |
695 | (lambda (key whom what src form subform) | |
696 | (list key whom what form subform)))) | |
697 | ||
698 | (pass-if-equal "invalid predicate name" | |
699 | '(syntax-error define-immutable-record-type | |
700 | "expected predicate name" | |
701 | (define-immutable-record-type :foobar | |
702 | (foobar x y) | |
703 | (x foobar-x) | |
704 | (y foobar-y)) | |
705 | (x foobar-x)) | |
706 | (catch 'syntax-error | |
707 | (lambda () | |
708 | (compile '(define-immutable-record-type :foobar | |
709 | (foobar x y) | |
710 | (x foobar-x) | |
711 | (y foobar-y)) | |
712 | #:env (current-module)) | |
713 | #f) | |
714 | (lambda (key whom what src form subform) | |
715 | (list key whom what form subform)))) | |
716 | ||
717 | (pass-if-equal "invalid field spec" | |
718 | '(syntax-error define-record-type | |
719 | "invalid field spec" | |
720 | (define-record-type :foobar | |
721 | (make-foobar x y) | |
722 | foobar? | |
723 | (x) | |
724 | (y foobar-y)) | |
725 | (x)) | |
726 | (catch 'syntax-error | |
727 | (lambda () | |
728 | (compile '(define-record-type :foobar | |
729 | (make-foobar x y) | |
730 | foobar? | |
731 | (x) | |
732 | (y foobar-y)) | |
733 | #:env (current-module)) | |
734 | #f) | |
735 | (lambda (key whom what src form subform) | |
736 | (list key whom what form subform)))) | |
737 | ||
738 | (pass-if-equal "unknown field in constructor spec" | |
739 | '(syntax-error define-record-type | |
740 | "unknown field in constructor spec" | |
741 | (define-record-type :foobar | |
742 | (make-foobar x z) | |
743 | foobar? | |
744 | (x foobar-x) | |
745 | (y foobar-y)) | |
746 | z) | |
747 | (catch 'syntax-error | |
748 | (lambda () | |
749 | (compile '(define-record-type :foobar | |
750 | (make-foobar x z) | |
751 | foobar? | |
752 | (x foobar-x) | |
753 | (y foobar-y)) | |
754 | #:env (current-module)) | |
755 | #f) | |
756 | (lambda (key whom what src form subform) | |
757 | (list key whom what form subform))))) | |
758 | ||
5ef102cc LC |
759 | (with-test-prefix "record compatibility" |
760 | ||
761 | (pass-if "record?" | |
762 | (record? (make-foo 1))) | |
763 | ||
764 | (pass-if "record-constructor" | |
765 | (equal? ((record-constructor :foo) 1) | |
766 | (make-foo 1)))) | |
d9e36897 MW |
767 | |
768 | ;;; Local Variables: | |
769 | ;;; mode: scheme | |
770 | ;;; eval: (put 'set-fields 'scheme-indent-function 1) | |
771 | ;;; End: |