1 ;;;; eval.test --- tests guile's evaluator -*- scheme -*-
2 ;;;; Copyright (C) 2000, 2001, 2006, 2007, 2009 Free Software Foundation, Inc.
4 ;;;; This library is free software; you can redistribute it and/or
5 ;;;; modify it under the terms of the GNU Lesser General Public
6 ;;;; License as published by the Free Software Foundation; either
7 ;;;; version 3 of the License, or (at your option) any later version.
9 ;;;; This library 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 GNU
12 ;;;; Lesser General Public License for more details.
14 ;;;; You should have received a copy of the GNU Lesser General Public
15 ;;;; License along with this library; if not, write to the Free Software
16 ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 (define-module (test-suite test-eval)
19 :use-module (test-suite lib)
20 :use-module ((srfi srfi-1) :select (unfold count))
21 :use-module (ice-9 documentation))
24 (define exception:bad-expression
25 (cons 'syntax-error "Bad expression"))
27 (define exception:failed-match
28 (cons 'syntax-error "failed to match any pattern"))
35 (define (documented? object)
36 (not (not (object-documentation object))))
43 (with-test-prefix "memoization"
45 (with-test-prefix "copy-tree"
47 (pass-if "(#t . #(#t))"
48 (let* ((foo (cons #t (vector #t)))
49 (bar (copy-tree foo)))
50 (vector-set! (cdr foo) 0 #f)
51 (equal? bar '(#t . #(#t)))))
53 (pass-if-exception "circular lists in forms"
54 exception:bad-expression
55 (let ((foo (list #f)))
59 (pass-if "transparency"
61 (eval x (current-module))
62 (equal? '(begin 1) x))))
69 (with-test-prefix "evaluator"
71 (with-test-prefix "symbol lookup"
73 (with-test-prefix "top level"
75 (with-test-prefix "unbound"
77 (pass-if-exception "variable reference"
81 (pass-if-exception "procedure"
85 (with-test-prefix "parameter error"
87 ;; This is currently a bug in guile:
88 ;; Macros are accepted as function parameters.
89 ;; Functions that 'apply' macros are rewritten!!!
91 (pass-if-exception "macro as argument"
92 exception:failed-match
94 '(let ((f (lambda (p a b) (p a b))))
97 (pass-if-exception "passing macro as parameter"
98 exception:failed-match
100 '(let* ((f (lambda (p a b) (p a b)))
101 (foo (procedure-source f)))
103 (equal? (procedure-source f) foo))))
111 (with-test-prefix "call"
113 (with-test-prefix "wrong number of arguments"
115 (pass-if-exception "((lambda () #f) 1)"
116 exception:wrong-num-args
119 (pass-if-exception "((lambda (x) #f))"
120 exception:wrong-num-args
123 (pass-if-exception "((lambda (x) #f) 1 2)"
124 exception:wrong-num-args
125 ((lambda (x) #f) 1 2))
127 (pass-if-exception "((lambda (x y) #f))"
128 exception:wrong-num-args
131 (pass-if-exception "((lambda (x y) #f) 1)"
132 exception:wrong-num-args
133 ((lambda (x y) #f) 1))
135 (pass-if-exception "((lambda (x y) #f) 1 2 3)"
136 exception:wrong-num-args
137 ((lambda (x y) #f) 1 2 3))
139 (pass-if-exception "((lambda (x . rest) #f))"
140 exception:wrong-num-args
141 ((lambda (x . rest) #f)))
143 (pass-if-exception "((lambda (x y . rest) #f))"
144 exception:wrong-num-args
145 ((lambda (x y . rest) #f)))
147 (pass-if-exception "((lambda (x y . rest) #f) 1)"
148 exception:wrong-num-args
149 ((lambda (x y . rest) #f) 1))))
155 (with-test-prefix "apply"
157 (with-test-prefix "scm_tc7_subr_2o"
159 ;; prior to guile 1.6.9 and 1.8.1 this called the function with
160 ;; SCM_UNDEFIEND, which in the case of make-vector resulted in
161 ;; wrong-type-arg, instead of the intended wrong-num-args
162 (pass-if-exception "0 args" exception:wrong-num-args
163 (apply make-vector '()))
166 (vector? (apply make-vector '(1))))
169 (vector? (apply make-vector '(1 2))))
171 ;; prior to guile 1.6.9 and 1.8.1 this error wasn't detected
172 (pass-if-exception "3 args" exception:wrong-num-args
173 (apply make-vector '(1 2 3)))))
179 (with-test-prefix "map"
181 ;; Is documentation available?
183 (expect-fail "documented?"
186 (with-test-prefix "argument error"
188 (with-test-prefix "non list argument"
191 (with-test-prefix "different length lists"
193 (pass-if-exception "first list empty"
194 exception:out-of-range
197 (pass-if-exception "second list empty"
198 exception:out-of-range
201 (pass-if-exception "first list shorter"
202 exception:out-of-range
205 (pass-if-exception "second list shorter"
206 exception:out-of-range
211 ;;; define with procedure-name
214 (define old-procnames-flag (memq 'procnames (debug-options)))
215 (debug-enable 'procnames)
217 ;; names are only set on top-level procedures (currently), so these can't be
220 (define foo-closure (lambda () "hello"))
221 (define bar-closure foo-closure)
222 ;; make sure that make-procedure-with-setter returns an anonymous
223 ;; procedure-with-setter by passing it an anonymous getter.
224 (define foo-pws (make-procedure-with-setter
226 (lambda (x y) (set-car! x y))))
227 (define bar-pws foo-pws)
229 (with-test-prefix "define set procedure-name"
232 (eq? 'foo-closure (procedure-name bar-closure)))
234 (pass-if "procedure-with-setter"
235 (eq? 'foo-pws (procedure-name bar-pws))))
237 (if old-procnames-flag
238 (debug-enable 'procnames)
239 (debug-disable 'procnames))
245 (with-test-prefix "promises"
247 (with-test-prefix "basic promise behaviour"
249 (pass-if "delay gives a promise"
250 (promise? (delay 1)))
252 (pass-if "force evaluates a promise"
253 (eqv? (force (delay (+ 1 2))) 3))
255 (pass-if "a forced promise is a promise"
256 (let ((p (delay (+ 1 2))))
260 (pass-if "forcing a forced promise works"
261 (let ((p (delay (+ 1 2))))
265 (pass-if "a promise is evaluated once"
272 (pass-if "a promise may call itself"
278 (if (> x 1) x (force p))))))
281 (pass-if "a promise carries its environment"
284 (set! p (delay (+ x 1))))
287 (pass-if "a forced promise does not reference its environment"
288 (let* ((g (make-guardian))
290 (let* ((x (cons #f #f)))
292 (set! p (delay (car x))))
295 (if (not (equal? (g) (cons #f #f)))
299 (with-test-prefix "extended promise behaviour"
301 (pass-if-exception "forcing a non-promise object is not supported"
302 exception:wrong-type-arg
305 (pass-if-exception "implicit forcing is not supported"
306 exception:wrong-type-arg
307 (+ (delay (* 3 7)) 13))
309 ;; Tests that require the debugging evaluator...
310 (with-debugging-evaluator
312 (pass-if "unmemoizing a promise"
315 (false-if-exception (lazy-catch #t
317 (let ((f (lambda (g) (delay (g)))))
320 (set! stack (make-stack #t)))))
322 (%make-void-port "w"))
330 (define (stack->frames stack)
331 ;; Return the list of frames comprising STACK.
333 (>= i (stack-length stack)))
339 (with-test-prefix "stacks"
340 (with-debugging-evaluator
342 (pass-if "stack involving a subr"
343 ;; The subr involving the error must appear exactly once on the stack.
347 (lazy-catch 'wrong-type-arg
349 ;; Trigger a `wrong-type-arg' exception.
350 (fluid-ref 'not-a-fluid))
352 (let* ((stack (make-stack #t))
353 (frames (stack->frames stack)))
355 (count (lambda (frame)
356 (and (frame-procedure? frame)
357 (eq? (frame-procedure frame)
363 (pass-if "stack involving a gsubr"
364 ;; The gsubr involving the error must appear exactly once on the stack.
365 ;; This is less obvious since gsubr application may require an
366 ;; additional `SCM_APPLY ()' call, which should not be visible to the
371 (lazy-catch 'wrong-type-arg
373 ;; Trigger a `wrong-type-arg' exception.
374 (hashq-ref 'wrong 'type 'arg))
376 (let* ((stack (make-stack #t))
377 (frames (stack->frames stack)))
379 (count (lambda (frame)
380 (and (frame-procedure? frame)
381 (eq? (frame-procedure frame)
388 ;;; letrec init evaluation
391 (with-test-prefix "letrec init evaluation"
393 (pass-if "lots of inits calculated in correct order"
394 (equal? (letrec ((a 'a) (b 'b) (c 'c) (d 'd)
395 (e 'e) (f 'f) (g 'g) (h 'h)
396 (i 'i) (j 'j) (k 'k) (l 'l)
397 (m 'm) (n 'n) (o 'o) (p 'p)
398 (q 'q) (r 'r) (s 's) (t 't)
399 (u 'u) (v 'v) (w 'w) (x 'x)
401 (list a b c d e f g h i j k l m
402 n o p q r s t u v w x y z))
403 '(a b c d e f g h i j k l m
404 n o p q r s t u v w x y z))))
410 (with-test-prefix "values"
412 (pass-if "single value"
413 (equal? 1 (values 1)))
415 (pass-if "call-with-values"
416 (equal? (call-with-values (lambda () (values 1 2 3 4)) list)
420 (equal? (values 1 2 3 4) (values 1 2 3 4))))
422 ;;; eval.test ends here