eval.test 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. ;;;; eval.test --- tests guile's evaluator -*- scheme -*-
  2. ;;;; Copyright (C) 2000, 2001, 2006, 2007, 2009 Free Software Foundation, Inc.
  3. ;;;;
  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 2.1 of the License, or (at your option) any later version.
  8. ;;;;
  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.
  13. ;;;;
  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
  17. (define-module (test-suite test-eval)
  18. :use-module (test-suite lib)
  19. :use-module ((srfi srfi-1) :select (unfold count))
  20. :use-module (ice-9 documentation))
  21. (define exception:bad-expression
  22. (cons 'syntax-error "Bad expression"))
  23. ;;;
  24. ;;; miscellaneous
  25. ;;;
  26. (define (documented? object)
  27. (not (not (object-documentation object))))
  28. ;;;
  29. ;;; memoization
  30. ;;;
  31. (with-test-prefix "memoization"
  32. (with-test-prefix "copy-tree"
  33. (pass-if "(#t . #(#t))"
  34. (let* ((foo (cons #t (vector #t)))
  35. (bar (copy-tree foo)))
  36. (vector-set! (cdr foo) 0 #f)
  37. (equal? bar '(#t . #(#t)))))
  38. (pass-if-exception "circular lists in forms"
  39. exception:bad-expression
  40. (let ((foo (list #f)))
  41. (set-cdr! foo foo)
  42. (copy-tree foo))))
  43. (pass-if "transparency"
  44. (let ((x '(begin 1)))
  45. (eval x (current-module))
  46. (equal? '(begin 1) x))))
  47. ;;;
  48. ;;; eval
  49. ;;;
  50. (with-test-prefix "evaluator"
  51. (with-test-prefix "symbol lookup"
  52. (with-test-prefix "top level"
  53. (with-test-prefix "unbound"
  54. (pass-if-exception "variable reference"
  55. exception:unbound-var
  56. x)
  57. (pass-if-exception "procedure"
  58. exception:unbound-var
  59. (x)))))
  60. (with-test-prefix "parameter error"
  61. ;; This is currently a bug in guile:
  62. ;; Macros are accepted as function parameters.
  63. ;; Functions that 'apply' macros are rewritten!!!
  64. (expect-fail-exception "macro as argument"
  65. exception:wrong-type-arg
  66. (let ((f (lambda (p a b) (p a b))))
  67. (f and #t #t)))
  68. (expect-fail-exception "passing macro as parameter"
  69. exception:wrong-type-arg
  70. (let* ((f (lambda (p a b) (p a b)))
  71. (foo (procedure-source f)))
  72. (f and #t #t)
  73. (equal? (procedure-source f) foo)))
  74. ))
  75. ;;;
  76. ;;; call
  77. ;;;
  78. (with-test-prefix "call"
  79. (with-test-prefix "wrong number of arguments"
  80. (pass-if-exception "((lambda () #f) 1)"
  81. exception:wrong-num-args
  82. ((lambda () #f) 1))
  83. (pass-if-exception "((lambda (x) #f))"
  84. exception:wrong-num-args
  85. ((lambda (x) #f)))
  86. (pass-if-exception "((lambda (x) #f) 1 2)"
  87. exception:wrong-num-args
  88. ((lambda (x) #f) 1 2))
  89. (pass-if-exception "((lambda (x y) #f))"
  90. exception:wrong-num-args
  91. ((lambda (x y) #f)))
  92. (pass-if-exception "((lambda (x y) #f) 1)"
  93. exception:wrong-num-args
  94. ((lambda (x y) #f) 1))
  95. (pass-if-exception "((lambda (x y) #f) 1 2 3)"
  96. exception:wrong-num-args
  97. ((lambda (x y) #f) 1 2 3))
  98. (pass-if-exception "((lambda (x . rest) #f))"
  99. exception:wrong-num-args
  100. ((lambda (x . rest) #f)))
  101. (pass-if-exception "((lambda (x y . rest) #f))"
  102. exception:wrong-num-args
  103. ((lambda (x y . rest) #f)))
  104. (pass-if-exception "((lambda (x y . rest) #f) 1)"
  105. exception:wrong-num-args
  106. ((lambda (x y . rest) #f) 1))))
  107. ;;;
  108. ;;; apply
  109. ;;;
  110. (with-test-prefix "apply"
  111. (with-test-prefix "scm_tc7_subr_2o"
  112. ;; prior to guile 1.6.9 and 1.8.1 this called the function with
  113. ;; SCM_UNDEFIEND, which in the case of make-vector resulted in
  114. ;; wrong-type-arg, instead of the intended wrong-num-args
  115. (pass-if-exception "0 args" exception:wrong-num-args
  116. (apply make-vector '()))
  117. (pass-if "1 arg"
  118. (vector? (apply make-vector '(1))))
  119. (pass-if "2 args"
  120. (vector? (apply make-vector '(1 2))))
  121. ;; prior to guile 1.6.9 and 1.8.1 this error wasn't detected
  122. (pass-if-exception "3 args" exception:wrong-num-args
  123. (apply make-vector '(1 2 3)))))
  124. ;;;
  125. ;;; map
  126. ;;;
  127. (with-test-prefix "map"
  128. ;; Is documentation available?
  129. (expect-fail "documented?"
  130. (documented? map))
  131. (with-test-prefix "argument error"
  132. (with-test-prefix "non list argument"
  133. #t)
  134. (with-test-prefix "different length lists"
  135. (pass-if-exception "first list empty"
  136. exception:out-of-range
  137. (map + '() '(1)))
  138. (pass-if-exception "second list empty"
  139. exception:out-of-range
  140. (map + '(1) '()))
  141. (pass-if-exception "first list shorter"
  142. exception:out-of-range
  143. (map + '(1) '(2 3)))
  144. (pass-if-exception "second list shorter"
  145. exception:out-of-range
  146. (map + '(1 2) '(3)))
  147. )))
  148. ;;;
  149. ;;; define with procedure-name
  150. ;;;
  151. (define old-procnames-flag (memq 'procnames (debug-options)))
  152. (debug-enable 'procnames)
  153. ;; names are only set on top-level procedures (currently), so these can't be
  154. ;; hidden in a let
  155. ;;
  156. (define foo-closure (lambda () "hello"))
  157. (define bar-closure foo-closure)
  158. (define foo-pws (make-procedure-with-setter car set-car!))
  159. (define bar-pws foo-pws)
  160. (with-test-prefix "define set procedure-name"
  161. (pass-if "closure"
  162. (eq? 'foo-closure (procedure-name bar-closure)))
  163. (pass-if "procedure-with-setter"
  164. (eq? 'foo-pws (pk (procedure-name bar-pws)))))
  165. (if old-procnames-flag
  166. (debug-enable 'procnames)
  167. (debug-disable 'procnames))
  168. ;;;
  169. ;;; promises
  170. ;;;
  171. (with-test-prefix "promises"
  172. (with-test-prefix "basic promise behaviour"
  173. (pass-if "delay gives a promise"
  174. (promise? (delay 1)))
  175. (pass-if "force evaluates a promise"
  176. (eqv? (force (delay (+ 1 2))) 3))
  177. (pass-if "a forced promise is a promise"
  178. (let ((p (delay (+ 1 2))))
  179. (force p)
  180. (promise? p)))
  181. (pass-if "forcing a forced promise works"
  182. (let ((p (delay (+ 1 2))))
  183. (force p)
  184. (eqv? (force p) 3)))
  185. (pass-if "a promise is evaluated once"
  186. (let* ((x 1)
  187. (p (delay (+ x 1))))
  188. (force p)
  189. (set! x (+ x 1))
  190. (eqv? (force p) 2)))
  191. (pass-if "a promise may call itself"
  192. (define p
  193. (let ((x 0))
  194. (delay
  195. (begin
  196. (set! x (+ x 1))
  197. (if (> x 1) x (force p))))))
  198. (eqv? (force p) 2))
  199. (pass-if "a promise carries its environment"
  200. (let* ((x 1) (p #f))
  201. (let* ((x 2))
  202. (set! p (delay (+ x 1))))
  203. (eqv? (force p) 3)))
  204. (pass-if "a forced promise does not reference its environment"
  205. (let* ((g (make-guardian))
  206. (p #f))
  207. (let* ((x (cons #f #f)))
  208. (g x)
  209. (set! p (delay (car x))))
  210. (force p)
  211. (gc)
  212. (if (not (equal? (g) (cons #f #f)))
  213. (throw 'unresolved)
  214. #t))))
  215. (with-test-prefix "extended promise behaviour"
  216. (pass-if-exception "forcing a non-promise object is not supported"
  217. exception:wrong-type-arg
  218. (force 1))
  219. (pass-if-exception "implicit forcing is not supported"
  220. exception:wrong-type-arg
  221. (+ (delay (* 3 7)) 13))
  222. ;; Tests that require the debugging evaluator...
  223. (with-debugging-evaluator
  224. (pass-if "unmemoizing a promise"
  225. (display-backtrace
  226. (let ((stack #f))
  227. (false-if-exception (lazy-catch #t
  228. (lambda ()
  229. (let ((f (lambda (g) (delay (g)))))
  230. (force (f error))))
  231. (lambda _
  232. (set! stack (make-stack #t)))))
  233. stack)
  234. (%make-void-port "w"))
  235. #t))))
  236. ;;;
  237. ;;; stacks
  238. ;;;
  239. (define (stack->frames stack)
  240. ;; Return the list of frames comprising STACK.
  241. (unfold (lambda (i)
  242. (>= i (stack-length stack)))
  243. (lambda (i)
  244. (stack-ref stack i))
  245. 1+
  246. 0))
  247. (with-test-prefix "stacks"
  248. (with-debugging-evaluator
  249. (pass-if "stack involving a subr"
  250. ;; The subr involving the error must appear exactly once on the stack.
  251. (catch 'result
  252. (lambda ()
  253. (start-stack 'foo
  254. (lazy-catch 'wrong-type-arg
  255. (lambda ()
  256. ;; Trigger a `wrong-type-arg' exception.
  257. (fluid-ref 'not-a-fluid))
  258. (lambda _
  259. (let* ((stack (make-stack #t))
  260. (frames (stack->frames stack)))
  261. (throw 'result
  262. (count (lambda (frame)
  263. (and (frame-procedure? frame)
  264. (eq? (frame-procedure frame)
  265. fluid-ref)))
  266. frames)))))))
  267. (lambda (key result)
  268. (= 1 result))))
  269. (pass-if "stack involving a gsubr"
  270. ;; The gsubr involving the error must appear exactly once on the stack.
  271. ;; This is less obvious since gsubr application may require an
  272. ;; additional `SCM_APPLY ()' call, which should not be visible to the
  273. ;; application.
  274. (catch 'result
  275. (lambda ()
  276. (start-stack 'foo
  277. (lazy-catch 'wrong-type-arg
  278. (lambda ()
  279. ;; Trigger a `wrong-type-arg' exception.
  280. (hashq-ref 'wrong 'type 'arg))
  281. (lambda _
  282. (let* ((stack (make-stack #t))
  283. (frames (stack->frames stack)))
  284. (throw 'result
  285. (count (lambda (frame)
  286. (and (frame-procedure? frame)
  287. (eq? (frame-procedure frame)
  288. hashq-ref)))
  289. frames)))))))
  290. (lambda (key result)
  291. (= 1 result))))))
  292. ;;;
  293. ;;; letrec init evaluation
  294. ;;;
  295. (with-test-prefix "letrec init evaluation"
  296. (pass-if "lots of inits calculated in correct order"
  297. (equal? (letrec ((a 'a) (b 'b) (c 'c) (d 'd)
  298. (e 'e) (f 'f) (g 'g) (h 'h)
  299. (i 'i) (j 'j) (k 'k) (l 'l)
  300. (m 'm) (n 'n) (o 'o) (p 'p)
  301. (q 'q) (r 'r) (s 's) (t 't)
  302. (u 'u) (v 'v) (w 'w) (x 'x)
  303. (y 'y) (z 'z))
  304. (list a b c d e f g h i j k l m
  305. n o p q r s t u v w x y z))
  306. '(a b c d e f g h i j k l m
  307. n o p q r s t u v w x y z))))
  308. ;;;
  309. ;;; values
  310. ;;;
  311. (with-test-prefix "values"
  312. (pass-if "single value"
  313. (equal? 1 (values 1)))
  314. (pass-if "call-with-values"
  315. (equal? (call-with-values (lambda () (values 1 2 3 4)) list)
  316. '(1 2 3 4)))
  317. (pass-if "equal?"
  318. (equal? (values 1 2 3 4) (values 1 2 3 4))))
  319. ;;; eval.test ends here