* Remove redundant test name prefix.
[bpt/guile.git] / test-suite / tests / environments.test
CommitLineData
5d3e2388
DH
1;;;; environments.test -*- scheme -*-
2;;;; Copyright (C) 2000 Free Software Foundation, Inc.
3;;;;
4;;;; This program is free software; you can redistribute it and/or modify
5;;;; it under the terms of the GNU General Public License as published by
6;;;; the Free Software Foundation; either version 2, or (at your option)
7;;;; any later version.
8;;;;
9;;;; This program is distributed in the hope that it will be useful,
10;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
11;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12;;;; GNU General Public License for more details.
13;;;;
14;;;; You should have received a copy of the GNU General Public License
15;;;; along with this software; see the file COPYING. If not, write to
16;;;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17;;;; Boston, MA 02111-1307 USA
18;;;;
19;;;; As a special exception, the Free Software Foundation gives permission
20;;;; for additional uses of the text contained in its release of GUILE.
21;;;;
22;;;; The exception is that, if you link the GUILE library with other files
23;;;; to produce an executable, this does not by itself cause the
24;;;; resulting executable to be covered by the GNU General Public License.
25;;;; Your use of that executable is in no way restricted on account of
26;;;; linking the GUILE library code into it.
27;;;;
28;;;; This exception does not however invalidate any other reasons why
29;;;; the executable file might be covered by the GNU General Public License.
30;;;;
31;;;; This exception applies only to the code released by the
32;;;; Free Software Foundation under the name GUILE. If you copy
33;;;; code from other Free Software Foundation releases into a copy of
34;;;; GUILE, as the General Public License permits, the exception does
35;;;; not apply to the code that you add in this way. To avoid misleading
36;;;; anyone as to the status of such modified files, you must delete
37;;;; this exception notice from them.
38;;;;
39;;;; If you write modifications of your own for GUILE, it is your choice
40;;;; whether to permit this exception to apply to your modifications.
41;;;; If you do not wish that, delete this exception notice.
42
43(use-modules (ice-9 documentation))
44
45
46;;;
47;;; miscellaneous
48;;;
49
50
51(define (documented? object)
5c96bc39 52 (not (not (object-documentation object))))
5d3e2388 53
5d3e2388
DH
54(define (folder sym val res)
55 (cons (cons sym val) res))
56
034b924f
DH
57(define (make-observer-func)
58 (let* ((counter 0))
59 (lambda args
60 (if (null? args)
61 counter
62 (set! counter (+ counter 1))))))
63
64(define (make-erroneous-observer-func)
65 (let* ((func (make-observer-func)))
66 (lambda args
67 (if (null? args)
68 (func)
69 (begin
70 (func args)
71 (error))))))
5d3e2388
DH
72
73;;;
74;;; leaf-environments
75;;;
76
77(with-test-prefix "leaf-environments"
78
79 (with-test-prefix "leaf-environment?"
80
81 (pass-if "documented?"
82 (documented? leaf-environment?))
83
84 (pass-if "non-environment-object"
85 (not (leaf-environment? #f))))
86
87
88 (with-test-prefix "make-leaf-environment"
89
90 (pass-if "documented?"
91 (documented? make-leaf-environment))
92
93 (pass-if "produces an environment"
94 (environment? (make-leaf-environment)))
95
96 (pass-if "produces a leaf-environment"
97 (leaf-environment? (make-leaf-environment)))
98
99 (pass-if "produces always a new environment"
100 (not (eq? (make-leaf-environment) (make-leaf-environment)))))
101
102
103 (with-test-prefix "bound, define, ref, set!, cell"
104
034b924f
DH
105 (pass-if "symbols are unbound by default"
106 (let* ((env (make-leaf-environment)))
5d3e2388
DH
107 (and (not (environment-bound? env 'a))
108 (not (environment-bound? env 'b))
034b924f
DH
109 (not (environment-bound? env 'c)))))
110
111 (pass-if "symbol is bound after define"
112 (let* ((env (make-leaf-environment)))
113 (environment-bound? env 'a)
114 (environment-define env 'a #t)
115 (environment-bound? env 'a)))
116
117 (pass-if "ref a defined symbol"
118 (let* ((env (make-leaf-environment)))
119 (environment-bound? env 'a)
120 (environment-bound? env 'b)
121 (environment-define env 'a #t)
122 (environment-define env 'b #f)
123 (and (environment-ref env 'a)
124 (not (environment-ref env 'b)))))
125
126 (pass-if "set! a defined symbol"
127 (let* ((env (make-leaf-environment)))
128 (environment-define env 'a #t)
129 (environment-define env 'b #f)
130 (environment-ref env 'a)
131 (environment-ref env 'b)
132 (environment-set! env 'a #f)
133 (environment-set! env 'b #t)
134 (and (not (environment-ref env 'a))
135 (environment-ref env 'b))))
136
137 (pass-if "get a read-only cell"
138 (let* ((env (make-leaf-environment)))
139 (environment-define env 'a #t)
5d3e2388 140 (let* ((cell (environment-cell env 'a #f)))
034b924f
DH
141 (and (cdr cell)
142 (begin
143 (environment-set! env 'a #f)
144 (not (cdr cell)))))))
5d3e2388 145
034b924f
DH
146 (pass-if "a read-only cell gets rebound after define"
147 (let* ((env (make-leaf-environment)))
148 (environment-define env 'a #t)
5d3e2388 149 (let* ((cell (environment-cell env 'a #f)))
034b924f
DH
150 (environment-define env 'a #f)
151 (not (eq? (environment-cell env 'a #f) cell)))))
5d3e2388 152
034b924f
DH
153 (pass-if "get a writable cell"
154 (let* ((env (make-leaf-environment)))
155 (environment-define env 'a #t)
5d3e2388
DH
156 (let* ((readable (environment-cell env 'a #f))
157 (writable (environment-cell env 'a #t)))
158 (and (eq? readable writable)
159 (begin
034b924f
DH
160 (environment-set! env 'a #f)
161 (not (cdr writable)))
5d3e2388 162 (begin
034b924f
DH
163 (set-cdr! writable #t)
164 (environment-ref env 'a))
5d3e2388 165 (begin
034b924f
DH
166 (set-cdr! (environment-cell env 'a #t) #f)
167 (not (cdr writable)))))))
5d3e2388 168
034b924f
DH
169 (pass-if "a writable cell gets rebound after define"
170 (let* ((env (make-leaf-environment)))
171 (environment-define env 'a #t)
5d3e2388 172 (let* ((cell (environment-cell env 'a #t)))
034b924f
DH
173 (environment-define env 'a #f)
174 (not (eq? (environment-cell env 'a #t) cell)))))
175
176 (pass-if "reference an undefined symbol"
177 (catch #t
178 (lambda ()
179 (environment-ref (make-leaf-environment) 'a)
180 #f)
181 (lambda args
182 #t)))
183
184 (pass-if "set! an undefined symbol"
185 (catch #t
186 (lambda ()
187 (environment-set! (make-leaf-environment) 'a)
188 #f)
189 (lambda args
190 #t)))
191
192 (pass-if "get a readable cell for an undefined symbol"
193 (catch #t
194 (lambda ()
195 (environment-cell (make-leaf-environment) 'a #f)
196 #f)
197 (lambda args
198 #t)))
199
200 (pass-if "get a writable cell for an undefined symbol"
201 (catch #t
202 (lambda ()
203 (environment-cell (make-leaf-environment) 'a #t)
204 #f)
205 (lambda args
206 #t))))
207
208
209 (with-test-prefix "undefine"
210
211 (pass-if "undefine a defined symbol"
212 (let* ((env (make-leaf-environment)))
213 (environment-define env 'a 1)
214 (environment-ref env 'a)
215 (environment-undefine env 'a)
216 (not (environment-bound? env 'a))))
5d3e2388 217
034b924f
DH
218 (pass-if "undefine an already undefined symbol"
219 (environment-undefine (make-leaf-environment) 'a)
220 #t))
221
222
223 (with-test-prefix "fold"
224
225 (pass-if "empty environment"
226 (let* ((env (make-leaf-environment)))
227 (eq? 'success (environment-fold env folder 'success))))
228
229 (pass-if "one symbol"
230 (let* ((env (make-leaf-environment)))
231 (environment-define env 'a #t)
232 (equal? '((a . #t)) (environment-fold env folder '()))))
233
234 (pass-if "two symbols"
235 (let* ((env (make-leaf-environment)))
236 (environment-define env 'a #t)
237 (environment-define env 'b #f)
238 (let ((folded (environment-fold env folder '())))
239 (or (equal? folded '((a . #t) (b . #f)))
240 (equal? folded '((b . #f) (a . #t))))))))
241
242
243 (with-test-prefix "observe"
244
245 (pass-if "observe an environment"
246 (let* ((env (make-leaf-environment)))
247 (environment-observe env (make-observer-func))
248 #t))
249
250 (pass-if "observe an environment twice"
251 (let* ((env (make-leaf-environment))
252 (observer-1 (environment-observe env (make-observer-func)))
253 (observer-2 (environment-observe env (make-observer-func))))
254 (not (eq? observer-1 observer-2))))
255
256 (pass-if "definition of an undefined symbol"
257 (let* ((env (make-leaf-environment))
258 (func (make-observer-func)))
259 (environment-observe env func)
260 (environment-define env 'a 1)
261 (eqv? (func) 1)))
262
263 (pass-if "definition of an already defined symbol"
264 (let* ((env (make-leaf-environment)))
265 (environment-define env 'a 1)
266 (let* ((func (make-observer-func)))
267 (environment-observe env func)
268 (environment-define env 'a 1)
269 (eqv? (func) 1))))
270
271 (pass-if "set!ing of a defined symbol"
272 (let* ((env (make-leaf-environment)))
273 (environment-define env 'a 1)
274 (let* ((func (make-observer-func)))
275 (environment-observe env func)
276 (environment-set! env 'a 1)
277 (eqv? (func) 0))))
278
279 (pass-if "undefining a defined symbol"
280 (let* ((env (make-leaf-environment)))
281 (environment-define env 'a 1)
282 (let* ((func (make-observer-func)))
283 (environment-observe env func)
284 (environment-undefine env 'a)
285 (eqv? (func) 1))))
286
287 (pass-if "undefining an already undefined symbol"
288 (let* ((env (make-leaf-environment))
289 (func (make-observer-func)))
290 (environment-observe env func)
291 (environment-undefine env 'a)
292 (eqv? (func) 0)))
293
294 (pass-if "unobserve an active observer"
295 (let* ((env (make-leaf-environment))
296 (func (make-observer-func))
297 (observer (environment-observe env func)))
298 (environment-unobserve observer)
299 (environment-define env 'a 1)
300 (eqv? (func) 0)))
301
302 (pass-if "unobserve an inactive observer"
303 (let* ((env (make-leaf-environment))
304 (func (make-observer-func))
305 (observer (environment-observe env func)))
306 (environment-unobserve observer)
307 (environment-unobserve observer)
308 #t)))
309
310
311 (with-test-prefix "observe-weak"
312
313 (pass-if "observe an environment"
314 (let* ((env (make-leaf-environment)))
315 (environment-observe-weak env (make-observer-func))
316 #t))
317
318 (pass-if "observe an environment twice"
319 (let* ((env (make-leaf-environment))
320 (observer-1 (environment-observe-weak env (make-observer-func)))
321 (observer-2 (environment-observe-weak env (make-observer-func))))
322 (not (eq? observer-1 observer-2))))
323
324 (pass-if "definition of an undefined symbol"
325 (let* ((env (make-leaf-environment))
326 (func (make-observer-func)))
327 (environment-observe-weak env func)
328 (environment-define env 'a 1)
329 (eqv? (func) 1)))
330
331 (pass-if "definition of an already defined symbol"
332 (let* ((env (make-leaf-environment)))
333 (environment-define env 'a 1)
334 (let* ((func (make-observer-func)))
335 (environment-observe-weak env func)
336 (environment-define env 'a 1)
337 (eqv? (func) 1))))
338
339 (pass-if "set!ing of a defined symbol"
340 (let* ((env (make-leaf-environment)))
341 (environment-define env 'a 1)
342 (let* ((func (make-observer-func)))
343 (environment-observe-weak env func)
344 (environment-set! env 'a 1)
345 (eqv? (func) 0))))
346
347 (pass-if "undefining a defined symbol"
348 (let* ((env (make-leaf-environment)))
349 (environment-define env 'a 1)
350 (let* ((func (make-observer-func)))
351 (environment-observe-weak env func)
352 (environment-undefine env 'a)
353 (eqv? (func) 1))))
354
355 (pass-if "undefining an already undefined symbol"
356 (let* ((env (make-leaf-environment))
357 (func (make-observer-func)))
358 (environment-observe-weak env func)
359 (environment-undefine env 'a)
360 (eqv? (func) 0)))
361
362 (pass-if "unobserve an active observer"
363 (let* ((env (make-leaf-environment))
364 (func (make-observer-func))
365 (observer (environment-observe-weak env func)))
366 (environment-unobserve observer)
367 (environment-define env 'a 1)
368 (eqv? (func) 0)))
369
370 (pass-if "unobserve an inactive observer"
371 (let* ((env (make-leaf-environment))
372 (func (make-observer-func))
373 (observer (environment-observe-weak env func)))
374 (environment-unobserve observer)
375 (environment-unobserve observer)
376 #t))
377
378 (pass-if "weak observer gets collected"
379 (gc)
380 (let* ((env (make-leaf-environment))
381 (func (make-observer-func)))
382 (environment-observe-weak env func)
383 (gc)
384 (environment-define env 'a 1)
41505259
DH
385 (if (not (eqv? (func) 0))
386 (throw 'unresolved) ; note: conservative scanning
387 #t))))
034b924f
DH
388
389
390 (with-test-prefix "erroneous observers"
391
392 (pass-if "update continues after error"
393 (let* ((env (make-leaf-environment))
394 (func-1 (make-erroneous-observer-func))
395 (func-2 (make-erroneous-observer-func)))
396 (environment-observe env func-1)
397 (environment-observe env func-2)
398 (catch #t
399 (lambda ()
400 (environment-define env 'a 1)
401 #f)
402 (lambda args
403 (and (eq? (func-1) 1)
404 (eq? (func-2) 1))))))))
405
406
407;;;
408;;; leaf-environment based eval-environments
409;;;
410
411(with-test-prefix "leaf-environment based eval-environments"
412
413 (with-test-prefix "eval-environment?"
414
415 (pass-if "documented?"
416 (documented? eval-environment?))
417
418 (pass-if "non-environment-object"
419 (not (eval-environment? #f)))
420
421 (pass-if "leaf-environment-object"
422 (not (eval-environment? (make-leaf-environment)))))
423
424
425 (with-test-prefix "make-eval-environment"
426
427 (pass-if "documented?"
428 (documented? make-eval-environment))
429
430 (let* ((local (make-leaf-environment))
431 (imported (make-leaf-environment)))
432
433 (pass-if "produces an environment"
434 (environment? (make-eval-environment local imported)))
435
436 (pass-if "produces an eval-environment"
437 (eval-environment? (make-eval-environment local imported)))
438
439 (pass-if "produces always a new environment"
440 (not (eq? (make-eval-environment local imported)
441 (make-eval-environment local imported))))))
442
443
444 (with-test-prefix "eval-environment-local"
445
446 (pass-if "documented?"
447 (documented? eval-environment-local))
448
449 (pass-if "returns local"
450 (let* ((local (make-leaf-environment))
451 (imported (make-leaf-environment))
452 (env (make-eval-environment local imported)))
453 (eq? (eval-environment-local env) local))))
454
455
456 (with-test-prefix "eval-environment-imported"
457
458 (pass-if "documented?"
459 (documented? eval-environment-imported))
460
461 (pass-if "returns imported"
462 (let* ((local (make-leaf-environment))
463 (imported (make-leaf-environment))
464 (env (make-eval-environment local imported)))
465 (eq? (eval-environment-imported env) imported))))
466
467
468 (with-test-prefix "bound, define, ref, set!, cell"
469
470 (pass-if "symbols are unbound by default"
471 (let* ((local (make-leaf-environment))
472 (imported (make-leaf-environment))
473 (env (make-eval-environment local imported)))
474 (and (not (environment-bound? env 'a))
475 (not (environment-bound? env 'b))
476 (not (environment-bound? env 'c)))))
477
478 (with-test-prefix "symbols bound in imported"
479
480 (pass-if "binding is visible"
481 (let* ((local (make-leaf-environment))
482 (imported (make-leaf-environment))
483 (env (make-eval-environment local imported)))
484 (environment-bound? env 'a)
485 (environment-define imported 'a #t)
486 (environment-bound? env 'a)))
487
488 (pass-if "ref works"
489 (let* ((local (make-leaf-environment))
490 (imported (make-leaf-environment))
491 (env (make-eval-environment local imported)))
492 (environment-bound? env 'a)
493 (environment-define imported 'a #t)
494 (environment-ref env 'a)))
495
496 (pass-if "set! works"
497 (let* ((local (make-leaf-environment))
498 (imported (make-leaf-environment))
499 (env (make-eval-environment local imported)))
500 (environment-define imported 'a #f)
501 (environment-set! env 'a #t)
502 (environment-ref imported 'a)))
503
504 (pass-if "cells are passed through"
505 (let* ((local (make-leaf-environment))
506 (imported (make-leaf-environment))
507 (env (make-eval-environment local imported)))
508 (environment-define imported 'a #t)
509 (let* ((imported-cell (environment-cell imported 'a #f))
510 (env-cell (environment-cell env 'a #f)))
511 (eq? env-cell imported-cell)))))
512
513 (with-test-prefix "symbols bound in local"
514
515 (pass-if "binding is visible"
516 (let* ((local (make-leaf-environment))
517 (imported (make-leaf-environment))
518 (env (make-eval-environment local imported)))
519 (environment-bound? env 'a)
520 (environment-define local 'a #t)
521 (environment-bound? env 'a)))
522
523 (pass-if "ref works"
524 (let* ((local (make-leaf-environment))
525 (imported (make-leaf-environment))
526 (env (make-eval-environment local imported)))
527 (environment-define local 'a #t)
528 (environment-ref env 'a)))
529
530 (pass-if "set! works"
531 (let* ((local (make-leaf-environment))
532 (imported (make-leaf-environment))
533 (env (make-eval-environment local imported)))
534 (environment-define local 'a #f)
535 (environment-set! env 'a #t)
536 (environment-ref local 'a)))
537
538 (pass-if "cells are passed through"
539 (let* ((local (make-leaf-environment))
540 (imported (make-leaf-environment))
541 (env (make-eval-environment local imported)))
542 (environment-define local 'a #t)
543 (let* ((local-cell (environment-cell local 'a #f))
544 (env-cell (environment-cell env 'a #f)))
545 (eq? env-cell local-cell)))))
546
547 (with-test-prefix "symbols bound in local and imported"
548
549 (pass-if "binding is visible"
550 (let* ((local (make-leaf-environment))
551 (imported (make-leaf-environment))
552 (env (make-eval-environment local imported)))
553 (environment-bound? env 'a)
554 (environment-define imported 'a #t)
555 (environment-define local 'a #f)
556 (environment-bound? env 'a)))
557
558 (pass-if "ref works"
559 (let* ((local (make-leaf-environment))
560 (imported (make-leaf-environment))
561 (env (make-eval-environment local imported)))
562 (environment-define imported 'a #f)
563 (environment-define local 'a #t)
564 (environment-ref env 'a)))
565
566 (pass-if "set! changes local"
567 (let* ((local (make-leaf-environment))
568 (imported (make-leaf-environment))
569 (env (make-eval-environment local imported)))
570 (environment-define imported 'a #f)
571 (environment-define local 'a #f)
572 (environment-set! env 'a #t)
573 (environment-ref local 'a)))
574
575 (pass-if "set! does not touch imported"
576 (let* ((local (make-leaf-environment))
577 (imported (make-leaf-environment))
578 (env (make-eval-environment local imported)))
579 (environment-define imported 'a #t)
580 (environment-define local 'a #t)
581 (environment-set! env 'a #f)
582 (environment-ref imported 'a)))
583
584 (pass-if "cells from local are passed through"
585 (let* ((local (make-leaf-environment))
586 (imported (make-leaf-environment))
587 (env (make-eval-environment local imported)))
588 (environment-define local 'a #t)
589 (let* ((local-cell (environment-cell local 'a #f))
590 (env-cell (environment-cell env 'a #f)))
591 (eq? env-cell local-cell)))))
592
593 (with-test-prefix "defining symbols"
594
595 (pass-if "symbols are bound in local after define"
596 (let* ((local (make-leaf-environment))
597 (imported (make-leaf-environment))
598 (env (make-eval-environment local imported)))
599 (environment-define env 'a #t)
600 (environment-bound? local 'a)))
601
602 (pass-if "cells in local get rebound after define"
603 (let* ((local (make-leaf-environment))
604 (imported (make-leaf-environment))
605 (env (make-eval-environment local imported)))
606 (environment-define env 'a #f)
607 (let* ((old-cell (environment-cell local 'a #f)))
608 (environment-define env 'a #f)
609 (let* ((new-cell (environment-cell local 'a #f)))
610 (not (eq? new-cell old-cell))))))
611
612 (pass-if "cells in imported get shadowed after define"
613 (let* ((local (make-leaf-environment))
614 (imported (make-leaf-environment))
615 (env (make-eval-environment local imported)))
616 (environment-define imported 'a #f)
617 (environment-define env 'a #t)
618 (environment-ref local 'a))))
619
620 (let* ((local (make-leaf-environment))
621 (imported (make-leaf-environment))
622 (env (make-eval-environment local imported)))
623
624 (pass-if "reference an undefined symbol"
5d3e2388
DH
625 (catch #t
626 (lambda ()
627 (environment-ref env 'b)
628 #f)
629 (lambda args
630 #t)))
631
034b924f 632 (pass-if "set! an undefined symbol"
5d3e2388
DH
633 (catch #t
634 (lambda ()
635 (environment-set! env 'b)
636 #f)
637 (lambda args
638 #t)))
639
034b924f 640 (pass-if "get a readable cell for an undefined symbol"
5d3e2388
DH
641 (catch #t
642 (lambda ()
643 (environment-cell env 'b #f)
644 #f)
645 (lambda args
646 #t)))
647
034b924f 648 (pass-if "get a writable cell for an undefined symbol"
5d3e2388
DH
649 (catch #t
650 (lambda ()
651 (environment-cell env 'b #t)
652 #f)
653 (lambda args
654 #t)))))
655
034b924f 656 (with-test-prefix "eval-environment-set-local!"
5d3e2388 657
034b924f
DH
658 (pass-if "documented?"
659 (documented? eval-environment-set-local!))
660
661 (pass-if "new binding becomes visible"
662 (let* ((old-local (make-leaf-environment))
663 (new-local (make-leaf-environment))
664 (imported (make-leaf-environment))
665 (env (make-eval-environment old-local imported)))
666 (environment-bound? env 'a)
667 (environment-define new-local 'a #t)
668 (eval-environment-set-local! env new-local)
669 (environment-bound? env 'a)))
670
671 (pass-if "existing binding is replaced"
672 (let* ((old-local (make-leaf-environment))
673 (new-local (make-leaf-environment))
674 (imported (make-leaf-environment))
675 (env (make-eval-environment old-local imported)))
676 (environment-define old-local 'a #f)
677 (environment-ref env 'a)
678 (environment-define new-local 'a #t)
679 (eval-environment-set-local! env new-local)
680 (environment-ref env 'a)))
681
682 (pass-if "undefined binding is removed"
683 (let* ((old-local (make-leaf-environment))
684 (new-local (make-leaf-environment))
685 (imported (make-leaf-environment))
686 (env (make-eval-environment old-local imported)))
687 (environment-define old-local 'a #f)
688 (environment-ref env 'a)
689 (eval-environment-set-local! env new-local)
690 (not (environment-bound? env 'a))))
691
692 (pass-if "binding in imported remains shadowed"
693 (let* ((old-local (make-leaf-environment))
694 (new-local (make-leaf-environment))
695 (imported (make-leaf-environment))
696 (env (make-eval-environment old-local imported)))
697 (environment-define imported 'a #f)
698 (environment-define old-local 'a #f)
699 (environment-ref env 'a)
700 (environment-define new-local 'a #t)
701 (eval-environment-set-local! env new-local)
702 (environment-ref env 'a)))
703
704 (pass-if "binding in imported gets shadowed"
705 (let* ((old-local (make-leaf-environment))
706 (new-local (make-leaf-environment))
707 (imported (make-leaf-environment))
708 (env (make-eval-environment old-local imported)))
709 (environment-define imported 'a #f)
710 (environment-ref env 'a)
711 (environment-define new-local 'a #t)
712 (eval-environment-set-local! env new-local)
713 (environment-ref env 'a)))
714
715 (pass-if "binding in imported becomes visible"
716 (let* ((old-local (make-leaf-environment))
717 (new-local (make-leaf-environment))
718 (imported (make-leaf-environment))
719 (env (make-eval-environment old-local imported)))
720 (environment-define imported 'a #t)
721 (environment-define old-local 'a #f)
722 (environment-ref env 'a)
723 (eval-environment-set-local! env new-local)
724 (environment-ref env 'a))))
725
726 (with-test-prefix "eval-environment-set-imported!"
5d3e2388 727
034b924f
DH
728 (pass-if "documented?"
729 (documented? eval-environment-set-imported!))
730
731 (pass-if "new binding becomes visible"
732 (let* ((local (make-leaf-environment))
733 (old-imported (make-leaf-environment))
734 (new-imported (make-leaf-environment))
735 (env (make-eval-environment local old-imported)))
736 (environment-bound? env 'a)
737 (environment-define new-imported 'a #t)
738 (eval-environment-set-imported! env new-imported)
739 (environment-bound? env 'a)))
740
741 (pass-if "existing binding is replaced"
742 (let* ((local (make-leaf-environment))
743 (old-imported (make-leaf-environment))
744 (new-imported (make-leaf-environment))
745 (env (make-eval-environment local old-imported)))
746 (environment-define old-imported 'a #f)
747 (environment-ref env 'a)
748 (environment-define new-imported 'a #t)
749 (eval-environment-set-imported! env new-imported)
750 (environment-ref env 'a)))
751
752 (pass-if "undefined binding is removed"
753 (let* ((local (make-leaf-environment))
754 (old-imported (make-leaf-environment))
755 (new-imported (make-leaf-environment))
756 (env (make-eval-environment local old-imported)))
757 (environment-define old-imported 'a #f)
758 (environment-ref env 'a)
759 (eval-environment-set-imported! env new-imported)
760 (not (environment-bound? env 'a))))
761
762 (pass-if "binding in imported remains shadowed"
763 (let* ((local (make-leaf-environment))
764 (old-imported (make-leaf-environment))
765 (new-imported (make-leaf-environment))
766 (env (make-eval-environment local old-imported)))
767 (environment-define local 'a #t)
768 (environment-define old-imported 'a #f)
769 (environment-ref env 'a)
770 (environment-define new-imported 'a #t)
771 (eval-environment-set-imported! env new-imported)
772 (environment-ref env 'a)))
773
774 (pass-if "binding in imported gets shadowed"
775 (let* ((local (make-leaf-environment))
776 (old-imported (make-leaf-environment))
777 (new-imported (make-leaf-environment))
778 (env (make-eval-environment local old-imported)))
779 (environment-define local 'a #t)
780 (environment-ref env 'a)
781 (environment-define new-imported 'a #f)
782 (eval-environment-set-imported! env new-imported)
783 (environment-ref env 'a))))
5d3e2388 784
034b924f 785 (with-test-prefix "undefine"
5d3e2388 786
034b924f
DH
787 (pass-if "undefine an already undefined symbol"
788 (let* ((local (make-leaf-environment))
789 (imported (make-leaf-environment))
790 (env (make-eval-environment local imported)))
791 (environment-undefine env 'a)
792 #t))
5d3e2388 793
034b924f
DH
794 (pass-if "undefine removes a binding from local"
795 (let* ((local (make-leaf-environment))
796 (imported (make-leaf-environment))
797 (env (make-eval-environment local imported)))
798 (environment-define local 'a #t)
799 (environment-undefine env 'a)
800 (not (environment-bound? local 'a))))
5d3e2388 801
034b924f
DH
802 (pass-if "undefine does not influence imported"
803 (let* ((local (make-leaf-environment))
804 (imported (make-leaf-environment))
805 (env (make-eval-environment local imported)))
806 (environment-define imported 'a #t)
807 (environment-undefine env 'a)
808 (environment-bound? imported 'a)))
5d3e2388 809
034b924f
DH
810 (pass-if "undefine an imported symbol does not undefine it"
811 (let* ((local (make-leaf-environment))
812 (imported (make-leaf-environment))
813 (env (make-eval-environment local imported)))
814 (environment-define imported 'a #t)
5d3e2388 815 (environment-undefine env 'a)
034b924f
DH
816 (environment-bound? env 'a)))
817
818 (pass-if "undefine unshadows an imported symbol"
819 (let* ((local (make-leaf-environment))
820 (imported (make-leaf-environment))
821 (env (make-eval-environment local imported)))
822 (environment-define imported 'a #t)
823 (environment-define local 'a #f)
824 (environment-undefine env 'a)
825 (environment-ref env 'a))))
5d3e2388 826
034b924f 827 (with-test-prefix "fold"
5d3e2388 828
034b924f
DH
829 (pass-if "empty environment"
830 (let* ((local (make-leaf-environment))
831 (imported (make-leaf-environment))
832 (env (make-eval-environment local imported)))
833 (eq? 'success (environment-fold env folder 'success))))
834
835 (pass-if "one symbol in local"
836 (let* ((local (make-leaf-environment))
837 (imported (make-leaf-environment))
838 (env (make-eval-environment local imported)))
839 (environment-define local 'a #t)
840 (equal? '((a . #t)) (environment-fold env folder '()))))
841
842 (pass-if "one symbol in imported"
843 (let* ((local (make-leaf-environment))
844 (imported (make-leaf-environment))
845 (env (make-eval-environment local imported)))
846 (environment-define imported 'a #t)
847 (equal? '((a . #t)) (environment-fold env folder '()))))
848
849 (pass-if "shadowed symbol"
850 (let* ((local (make-leaf-environment))
851 (imported (make-leaf-environment))
852 (env (make-eval-environment local imported)))
853 (environment-define local 'a #t)
854 (environment-define imported 'a #f)
855 (equal? '((a . #t)) (environment-fold env folder '()))))
856
857 (pass-if "one symbol each"
858 (let* ((local (make-leaf-environment))
859 (imported (make-leaf-environment))
860 (env (make-eval-environment local imported)))
861 (environment-define local 'a #t)
862 (environment-define imported 'b #f)
863 (let ((folded (environment-fold env folder '())))
864 (or (equal? folded '((a . #t) (b . #f)))
865 (equal? folded '((b . #f) (a . #t))))))))
5d3e2388
DH
866
867
868 (with-test-prefix "observe"
869
034b924f
DH
870 (pass-if "observe an environment"
871 (let* ((local (make-leaf-environment))
872 (imported (make-leaf-environment))
873 (env (make-eval-environment local imported)))
874 (environment-observe env (make-observer-func))
875 #t))
876
877 (pass-if "observe an environment twice"
878 (let* ((local (make-leaf-environment))
879 (imported (make-leaf-environment))
880 (env (make-eval-environment local imported))
881 (observer-1 (environment-observe env (make-observer-func)))
882 (observer-2 (environment-observe env (make-observer-func))))
883 (not (eq? observer-1 observer-2))))
884
885 (pass-if "definition of an undefined symbol"
886 (let* ((local (make-leaf-environment))
887 (imported (make-leaf-environment))
888 (env (make-eval-environment local imported))
889 (func (make-observer-func)))
890 (environment-observe env func)
5d3e2388 891 (environment-define env 'a 1)
034b924f 892 (eqv? (func) 1)))
5d3e2388 893
034b924f
DH
894 (pass-if "definition of an already defined symbol"
895 (let* ((local (make-leaf-environment))
896 (imported (make-leaf-environment))
897 (env (make-eval-environment local imported)))
5d3e2388 898 (environment-define env 'a 1)
034b924f
DH
899 (let* ((func (make-observer-func)))
900 (environment-observe env func)
901 (environment-define env 'a 1)
902 (eqv? (func) 1))))
903
904 (pass-if "set!ing of a defined symbol"
905 (let* ((local (make-leaf-environment))
906 (imported (make-leaf-environment))
907 (env (make-eval-environment local imported)))
908 (environment-define env 'a 1)
909 (let* ((func (make-observer-func)))
910 (environment-observe env func)
911 (environment-set! env 'a 1)
912 (eqv? (func) 0))))
913
914 (pass-if "undefining a defined symbol"
915 (let* ((local (make-leaf-environment))
916 (imported (make-leaf-environment))
917 (env (make-eval-environment local imported)))
918 (environment-define env 'a 1)
919 (let* ((func (make-observer-func)))
920 (environment-observe env func)
921 (environment-undefine env 'a)
922 (eqv? (func) 1))))
923
924 (pass-if "undefining an already undefined symbol"
925 (let* ((local (make-leaf-environment))
926 (imported (make-leaf-environment))
927 (env (make-eval-environment local imported))
928 (func (make-observer-func)))
929 (environment-observe env func)
5d3e2388 930 (environment-undefine env 'a)
034b924f
DH
931 (eqv? (func) 0)))
932
933 (pass-if "unobserve an active observer"
934 (let* ((local (make-leaf-environment))
935 (imported (make-leaf-environment))
936 (env (make-eval-environment local imported))
937 (func (make-observer-func))
938 (observer (environment-observe env func)))
5d3e2388
DH
939 (environment-unobserve observer)
940 (environment-define env 'a 1)
034b924f
DH
941 (eqv? (func) 0)))
942
943 (pass-if "unobserve an inactive observer"
944 (let* ((local (make-leaf-environment))
945 (imported (make-leaf-environment))
946 (env (make-eval-environment local imported))
947 (func (make-observer-func))
948 (observer (environment-observe env func)))
949 (environment-unobserve observer)
5d3e2388
DH
950 (environment-unobserve observer)
951 #t)))
952
953
954 (with-test-prefix "observe-weak"
955
034b924f
DH
956 (pass-if "observe an environment"
957 (let* ((local (make-leaf-environment))
958 (imported (make-leaf-environment))
959 (env (make-eval-environment local imported)))
960 (environment-observe-weak env (make-observer-func))
961 #t))
962
963 (pass-if "observe an environment twice"
964 (let* ((local (make-leaf-environment))
965 (imported (make-leaf-environment))
966 (env (make-eval-environment local imported))
967 (observer-1 (environment-observe-weak env (make-observer-func)))
968 (observer-2 (environment-observe-weak env (make-observer-func))))
969 (not (eq? observer-1 observer-2))))
970
971 (pass-if "definition of an undefined symbol"
972 (let* ((local (make-leaf-environment))
973 (imported (make-leaf-environment))
974 (env (make-eval-environment local imported))
975 (func (make-observer-func)))
976 (environment-observe-weak env func)
5d3e2388 977 (environment-define env 'a 1)
034b924f 978 (eqv? (func) 1)))
5d3e2388 979
034b924f
DH
980 (pass-if "definition of an already defined symbol"
981 (let* ((local (make-leaf-environment))
982 (imported (make-leaf-environment))
983 (env (make-eval-environment local imported)))
5d3e2388 984 (environment-define env 'a 1)
034b924f
DH
985 (let* ((func (make-observer-func)))
986 (environment-observe-weak env func)
987 (environment-define env 'a 1)
988 (eqv? (func) 1))))
989
990 (pass-if "set!ing of a defined symbol"
991 (let* ((local (make-leaf-environment))
992 (imported (make-leaf-environment))
993 (env (make-eval-environment local imported)))
994 (environment-define env 'a 1)
995 (let* ((func (make-observer-func)))
996 (environment-observe-weak env func)
997 (environment-set! env 'a 1)
998 (eqv? (func) 0))))
999
1000 (pass-if "undefining a defined symbol"
1001 (let* ((local (make-leaf-environment))
1002 (imported (make-leaf-environment))
1003 (env (make-eval-environment local imported)))
1004 (environment-define env 'a 1)
1005 (let* ((func (make-observer-func)))
1006 (environment-observe-weak env func)
1007 (environment-undefine env 'a)
1008 (eqv? (func) 1))))
1009
1010 (pass-if "undefining an already undefined symbol"
1011 (let* ((local (make-leaf-environment))
1012 (imported (make-leaf-environment))
1013 (env (make-eval-environment local imported))
1014 (func (make-observer-func)))
1015 (environment-observe-weak env func)
5d3e2388 1016 (environment-undefine env 'a)
034b924f
DH
1017 (eqv? (func) 0)))
1018
1019 (pass-if "unobserve an active observer"
1020 (let* ((local (make-leaf-environment))
1021 (imported (make-leaf-environment))
1022 (env (make-eval-environment local imported))
1023 (func (make-observer-func))
1024 (observer (environment-observe-weak env func)))
5d3e2388
DH
1025 (environment-unobserve observer)
1026 (environment-define env 'a 1)
034b924f
DH
1027 (eqv? (func) 0)))
1028
1029 (pass-if "unobserve an inactive observer"
1030 (let* ((local (make-leaf-environment))
1031 (imported (make-leaf-environment))
1032 (env (make-eval-environment local imported))
1033 (func (make-observer-func))
1034 (observer (environment-observe-weak env func)))
5d3e2388 1035 (environment-unobserve observer)
034b924f
DH
1036 (environment-unobserve observer)
1037 #t))
1038
1039 (pass-if "weak observer gets collected"
1040 (gc)
1041 (let* ((local (make-leaf-environment))
1042 (imported (make-leaf-environment))
1043 (env (make-eval-environment local imported))
1044 (func (make-observer-func)))
5d3e2388 1045 (environment-observe-weak env func)
034b924f 1046 (gc)
5d3e2388 1047 (environment-define env 'a 1)
41505259
DH
1048 (if (not (eqv? (func) 0))
1049 (throw 'unresolved) ; note: conservative scanning
1050 #t))))
034b924f
DH
1051
1052
1053 (with-test-prefix "erroneous observers"
1054
1055 (pass-if "update continues after error"
1056 (let* ((local (make-leaf-environment))
1057 (imported (make-leaf-environment))
1058 (env (make-eval-environment local imported))
1059 (func-1 (make-erroneous-observer-func))
1060 (func-2 (make-erroneous-observer-func)))
5d3e2388
DH
1061 (environment-observe env func-1)
1062 (environment-observe env func-2)
1063 (catch #t
1064 (lambda ()
1065 (environment-define env 'a 1)
1066 #f)
1067 (lambda args
034b924f
DH
1068 (and (eq? (func-1) 1)
1069 (eq? (func-2) 1))))))))
1070
1071
1072;;;
1073;;; leaf-environment based import-environments
1074;;;
1075
1076(with-test-prefix "leaf-environment based import-environments"
1077
1078 (with-test-prefix "import-environment?"
1079
1080 (pass-if "documented?"
1081 (documented? import-environment?))
1082
1083 (pass-if "non-environment-object"
1084 (not (import-environment? #f)))
1085
1086 (pass-if "leaf-environment-object"
1087 (not (import-environment? (make-leaf-environment))))
1088
1089 (pass-if "eval-environment-object"
1090 (let* ((local (make-leaf-environment))
1091 (imported (make-leaf-environment))
1092 (env (make-eval-environment local imported)))
1093 (not (import-environment? (make-leaf-environment))))))
1094
1095
1096 (with-test-prefix "make-import-environment"
1097
1098 (pass-if "documented?"
1099 (documented? make-import-environment))))
1100