eval.test 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. ;;;; eval.test --- tests guile's evaluator -*- scheme -*-
  2. ;;;; Copyright (C) 2000, 2001, 2006, 2007, 2009, 2010, 2011, 2012, 2013, 2014 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 3 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 ((system vm vm) :select (call-with-stack-overflow-handler))
  21. :use-module ((system vm frame) :select (frame-call-representation))
  22. :use-module (ice-9 documentation)
  23. :use-module (ice-9 local-eval))
  24. (define exception:bad-expression
  25. (cons 'syntax-error "Bad expression"))
  26. (define exception:failed-match
  27. (cons 'syntax-error "failed to match any pattern"))
  28. (define exception:not-a-list
  29. (cons 'wrong-type-arg "Not a list"))
  30. (define exception:wrong-length
  31. (cons 'wrong-type-arg "wrong length"))
  32. ;;;
  33. ;;; miscellaneous
  34. ;;;
  35. (define (documented? object)
  36. (not (not (object-documentation object))))
  37. ;;;
  38. ;;; memoization
  39. ;;;
  40. (with-test-prefix "memoization"
  41. (with-test-prefix "copy-tree"
  42. (pass-if "(#t . #(#t))"
  43. (let* ((foo (cons #t (vector #t)))
  44. (bar (copy-tree foo)))
  45. (vector-set! (cdr foo) 0 #f)
  46. (equal? bar '(#t . #(#t)))))
  47. (pass-if-exception "circular lists in forms"
  48. exception:wrong-type-arg
  49. (let ((foo (list #f)))
  50. (set-cdr! foo foo)
  51. (copy-tree foo))))
  52. (pass-if "transparency"
  53. (let ((x '(begin 1)))
  54. (eval x (current-module))
  55. (equal? '(begin 1) x))))
  56. ;;;
  57. ;;; eval
  58. ;;;
  59. (with-test-prefix "evaluator"
  60. (pass-if "definitions return #<unspecified>"
  61. (eq? (primitive-eval '(define test-var 'foo))
  62. (if #f #f)))
  63. (with-test-prefix "symbol lookup"
  64. (with-test-prefix "top level"
  65. (with-test-prefix "unbound"
  66. (pass-if-exception "variable reference"
  67. exception:unbound-var
  68. x)
  69. (pass-if-exception "procedure"
  70. exception:unbound-var
  71. (x)))))
  72. (with-test-prefix "parameter error"
  73. ;; This is currently a bug in guile:
  74. ;; Macros are accepted as function parameters.
  75. ;; Functions that 'apply' macros are rewritten!!!
  76. (pass-if-exception "macro as argument"
  77. exception:failed-match
  78. (primitive-eval
  79. '(let ((f (lambda (p a b) (p a b))))
  80. (f and #t #t))))
  81. (pass-if-exception "passing macro as parameter"
  82. exception:failed-match
  83. (primitive-eval
  84. '(let* ((f (lambda (p a b) (p a b)))
  85. (foo (procedure-source f)))
  86. (f and #t #t)
  87. (equal? (procedure-source f) foo))))
  88. ))
  89. ;;;
  90. ;;; call
  91. ;;;
  92. (with-test-prefix "call"
  93. (with-test-prefix "wrong number of arguments"
  94. (pass-if-exception "((lambda () #f) 1)"
  95. exception:wrong-num-args
  96. ((lambda () #f) 1))
  97. (pass-if-exception "((lambda (x) #f))"
  98. exception:wrong-num-args
  99. ((lambda (x) #f)))
  100. (pass-if-exception "((lambda (x) #f) 1 2)"
  101. exception:wrong-num-args
  102. ((lambda (x) #f) 1 2))
  103. (pass-if-exception "((lambda (x y) #f))"
  104. exception:wrong-num-args
  105. ((lambda (x y) #f)))
  106. (pass-if-exception "((lambda (x y) #f) 1)"
  107. exception:wrong-num-args
  108. ((lambda (x y) #f) 1))
  109. (pass-if-exception "((lambda (x y) #f) 1 2 3)"
  110. exception:wrong-num-args
  111. ((lambda (x y) #f) 1 2 3))
  112. (pass-if-exception "((lambda (x . rest) #f))"
  113. exception:wrong-num-args
  114. ((lambda (x . rest) #f)))
  115. (pass-if-exception "((lambda (x y . rest) #f))"
  116. exception:wrong-num-args
  117. ((lambda (x y . rest) #f)))
  118. (pass-if-exception "((lambda (x y . rest) #f) 1)"
  119. exception:wrong-num-args
  120. ((lambda (x y . rest) #f) 1))))
  121. ;;;
  122. ;;; apply
  123. ;;;
  124. (with-test-prefix "apply"
  125. (with-test-prefix "scm_tc7_subr_2o"
  126. ;; prior to guile 1.6.9 and 1.8.1 this called the function with
  127. ;; SCM_UNDEFINED, which in the case of make-vector resulted in
  128. ;; wrong-type-arg, instead of the intended wrong-num-args
  129. (pass-if-exception "0 args" exception:wrong-num-args
  130. (apply make-vector '()))
  131. (pass-if "1 arg"
  132. (vector? (apply make-vector '(1))))
  133. (pass-if "2 args"
  134. (vector? (apply make-vector '(1 2))))
  135. ;; prior to guile 1.6.9 and 1.8.1 this error wasn't detected
  136. (pass-if-exception "3 args" exception:wrong-num-args
  137. (apply make-vector '(1 2 3)))))
  138. ;;;
  139. ;;; map
  140. ;;;
  141. (with-test-prefix "map"
  142. ;; Is documentation available?
  143. (expect-fail "documented?"
  144. (documented? map))
  145. (with-test-prefix "argument error"
  146. (with-test-prefix "non list argument"
  147. #t)
  148. (with-test-prefix "different length lists"
  149. (pass-if-exception "first list empty"
  150. exception:wrong-length
  151. (map + '() '(1)))
  152. (pass-if-exception "second list empty"
  153. exception:wrong-length
  154. (map + '(1) '()))
  155. (pass-if-exception "first list shorter"
  156. exception:wrong-length
  157. (map + '(1) '(2 3)))
  158. (pass-if-exception "second list shorter"
  159. exception:wrong-length
  160. (map + '(1 2) '(3)))
  161. )))
  162. (with-test-prefix "for-each"
  163. (pass-if-exception "1 arg, non-list, even number of elements"
  164. exception:not-a-list
  165. (for-each values '(1 2 3 4 . 5)))
  166. (pass-if-exception "1 arg, non-list, odd number of elements"
  167. exception:not-a-list
  168. (for-each values '(1 2 3 . 4))))
  169. ;;;
  170. ;;; define with procedure-name
  171. ;;;
  172. ;; names are only set on top-level procedures (currently), so these can't be
  173. ;; hidden in a let
  174. ;;
  175. (define foo-closure (lambda () "hello"))
  176. (define bar-closure foo-closure)
  177. ;; make sure that make-procedure-with-setter returns an anonymous
  178. ;; procedure-with-setter by passing it an anonymous getter.
  179. (define foo-pws (make-procedure-with-setter
  180. (lambda (x) (car x))
  181. (lambda (x y) (set-car! x y))))
  182. (define bar-pws foo-pws)
  183. (with-test-prefix "define set procedure-name"
  184. (pass-if "closure"
  185. (eq? 'foo-closure (procedure-name bar-closure)))
  186. (expect-fail "procedure-with-setter" ; FIXME: `pass-if' when it's supported
  187. (eq? 'foo-pws (procedure-name bar-pws))))
  188. ;;;
  189. ;;; promises
  190. ;;;
  191. (with-test-prefix "promises"
  192. (with-test-prefix "basic promise behaviour"
  193. (pass-if "delay gives a promise"
  194. (promise? (delay 1)))
  195. (pass-if "force evaluates a promise"
  196. (eqv? (force (delay (+ 1 2))) 3))
  197. (pass-if "a forced promise is a promise"
  198. (let ((p (delay (+ 1 2))))
  199. (force p)
  200. (promise? p)))
  201. (pass-if "forcing a forced promise works"
  202. (let ((p (delay (+ 1 2))))
  203. (force p)
  204. (eqv? (force p) 3)))
  205. (pass-if "a promise is evaluated once"
  206. (let* ((x 1)
  207. (p (delay (+ x 1))))
  208. (force p)
  209. (set! x (+ x 1))
  210. (eqv? (force p) 2)))
  211. (pass-if "a promise may call itself"
  212. (define p
  213. (let ((x 0))
  214. (delay
  215. (begin
  216. (set! x (+ x 1))
  217. (if (> x 1) x (force p))))))
  218. (eqv? (force p) 2))
  219. (pass-if "a promise carries its environment"
  220. (let* ((x 1) (p #f))
  221. (let* ((x 2))
  222. (set! p (delay (+ x 1))))
  223. (eqv? (force p) 3)))
  224. (pass-if "a forced promise does not reference its environment"
  225. (let* ((g (make-guardian))
  226. (p #f))
  227. (let* ((x (cons #f #f)))
  228. (g x)
  229. (set! p (delay (car x))))
  230. (force p)
  231. (gc)
  232. ;; Though this test works reliably when running just eval.test,
  233. ;; it often does the unresolved case when running the full
  234. ;; suite. Adding this extra gc makes the full-suite behavior
  235. ;; pass more reliably.
  236. (gc)
  237. (if (not (equal? (g) (cons #f #f)))
  238. (throw 'unresolved)
  239. #t))))
  240. (with-test-prefix "extended promise behaviour"
  241. (pass-if-exception "forcing a non-promise object is not supported"
  242. exception:wrong-type-arg
  243. (force 1))
  244. (pass-if "unmemoizing a promise"
  245. (display-backtrace
  246. (let ((stack #f))
  247. (false-if-exception
  248. (with-throw-handler #t
  249. (lambda ()
  250. (let ((f (lambda (g) (delay (g)))))
  251. (force (f error))))
  252. (lambda _
  253. (set! stack (make-stack #t)))))
  254. stack)
  255. (%make-void-port "w"))
  256. #t)))
  257. ;;;
  258. ;;; stacks
  259. ;;;
  260. (define (stack->frames stack)
  261. ;; Return the list of frames comprising STACK.
  262. (unfold (lambda (i)
  263. (>= i (stack-length stack)))
  264. (lambda (i)
  265. (stack-ref stack i))
  266. 1+
  267. 0))
  268. (define (make-tagged-trimmed-stack tag spec)
  269. (catch 'result
  270. (lambda ()
  271. (call-with-prompt
  272. tag
  273. (lambda ()
  274. (with-throw-handler 'wrong-type-arg
  275. (lambda () (substring 'wrong 'type 'arg))
  276. (lambda _ (throw 'result (apply make-stack spec)))))
  277. (lambda () (throw 'make-stack-failed))))
  278. (lambda (key result) result)))
  279. (define tag (make-prompt-tag "foo"))
  280. (with-test-prefix "stacks"
  281. (pass-if "stack involving a primitive"
  282. ;; The primitive involving the error must appear exactly once on the
  283. ;; stack.
  284. (let* ((stack (make-tagged-trimmed-stack tag '(#t)))
  285. (frames (stack->frames stack))
  286. (num (count (lambda (frame) (eq? (frame-procedure-name frame)
  287. 'substring))
  288. frames)))
  289. (= num 1)))
  290. (pass-if "arguments of a primitive stack frame"
  291. ;; Create a stack with two primitive frames and make sure the
  292. ;; arguments are correct.
  293. (let* ((stack (make-tagged-trimmed-stack tag '(#t)))
  294. (call-list (map frame-call-representation (stack->frames stack))))
  295. (and (equal? (car call-list) '(make-stack #t))
  296. (pair? (member '(substring wrong type arg)
  297. (cdr call-list))))))
  298. (pass-if "inner trim with prompt tag"
  299. (let* ((stack (make-tagged-trimmed-stack tag `(#t ,tag)))
  300. (frames (stack->frames stack)))
  301. ;; the top frame on the stack is the lambda inside the 'catch, and the
  302. ;; next frame is the (catch 'result ...)
  303. (and (eq? (car (frame-call-representation (cadr frames)))
  304. 'catch)
  305. (eq? (car (frame-arguments (cadr frames)))
  306. 'result))))
  307. (pass-if "outer trim with prompt tag"
  308. (let* ((stack (make-tagged-trimmed-stack tag `(#t 0 ,tag)))
  309. (frames (stack->frames stack)))
  310. ;; the top frame on the stack is the make-stack call, and the last
  311. ;; frame is the (with-throw-handler 'wrong-type-arg ...)
  312. (and (eq? (car (frame-call-representation (car frames)))
  313. 'make-stack)
  314. (eq? (car (frame-call-representation (car (last-pair frames))))
  315. 'with-throw-handler)))))
  316. ;;;
  317. ;;; letrec init evaluation
  318. ;;;
  319. (with-test-prefix "letrec init evaluation"
  320. (pass-if "lots of inits calculated in correct order"
  321. (equal? (letrec ((a 'a) (b 'b) (c 'c) (d 'd)
  322. (e 'e) (f 'f) (g 'g) (h 'h)
  323. (i 'i) (j 'j) (k 'k) (l 'l)
  324. (m 'm) (n 'n) (o 'o) (p 'p)
  325. (q 'q) (r 'r) (s 's) (t 't)
  326. (u 'u) (v 'v) (w 'w) (x 'x)
  327. (y 'y) (z 'z))
  328. (list a b c d e f g h i j k l m
  329. n o p q r s t u v w x y z))
  330. '(a b c d e f g h i j k l m
  331. n o p q r s t u v w x y z))))
  332. ;;;
  333. ;;; values
  334. ;;;
  335. (with-test-prefix "values"
  336. (pass-if "single value"
  337. (equal? 1 (values 1)))
  338. (pass-if "call-with-values"
  339. (equal? (call-with-values (lambda () (values 1 2 3 4)) list)
  340. '(1 2 3 4)))
  341. (pass-if "equal?"
  342. (equal? (values 1 2 3 4) (values 1 2 3 4))))
  343. ;;;
  344. ;;; stack overflow handling
  345. ;;;
  346. (with-test-prefix "stack overflow handlers"
  347. (define (trigger-overflow)
  348. (trigger-overflow)
  349. (error "not reached"))
  350. (define (dynwind-test n)
  351. (catch 'foo
  352. (lambda ()
  353. (call-with-stack-overflow-handler n
  354. (lambda ()
  355. (dynamic-wind (lambda () #t)
  356. trigger-overflow
  357. trigger-overflow))
  358. (lambda ()
  359. (throw 'foo))))
  360. (lambda _ #t)))
  361. (pass-if-exception "limit should be number"
  362. exception:wrong-type-arg
  363. (call-with-stack-overflow-handler #t
  364. trigger-overflow trigger-overflow))
  365. (pass-if-exception "limit should be exact integer"
  366. exception:wrong-type-arg
  367. (call-with-stack-overflow-handler 2.0
  368. trigger-overflow trigger-overflow))
  369. (pass-if-exception "limit should be nonnegative"
  370. exception:out-of-range
  371. (call-with-stack-overflow-handler -1
  372. trigger-overflow trigger-overflow))
  373. (pass-if-exception "limit should be positive"
  374. exception:out-of-range
  375. (call-with-stack-overflow-handler 0
  376. trigger-overflow trigger-overflow))
  377. (pass-if-exception "limit should be within address space"
  378. exception:out-of-range
  379. (call-with-stack-overflow-handler (ash 1 64)
  380. trigger-overflow trigger-overflow))
  381. (pass-if "exception on overflow"
  382. (catch 'foo
  383. (lambda ()
  384. (call-with-stack-overflow-handler 10000
  385. trigger-overflow
  386. (lambda ()
  387. (throw 'foo))))
  388. (lambda _ #t)))
  389. (pass-if "exception on overflow with dynwind"
  390. ;; Try all limits between 1 and 200 words.
  391. (let lp ((n 1))
  392. (or (= n 200)
  393. (and (dynwind-test n)
  394. (lp (1+ n))))))
  395. (pass-if-exception "overflow handler should return number"
  396. exception:wrong-type-arg
  397. (call-with-stack-overflow-handler 1000
  398. trigger-overflow
  399. (lambda () #t)))
  400. (pass-if-exception "overflow handler should return exact integer"
  401. exception:wrong-type-arg
  402. (call-with-stack-overflow-handler 1000
  403. trigger-overflow
  404. (lambda () 2.0)))
  405. (pass-if-exception "overflow handler should be nonnegative"
  406. exception:out-of-range
  407. (call-with-stack-overflow-handler 1000
  408. trigger-overflow
  409. (lambda () -1)))
  410. (pass-if-exception "overflow handler should be positive"
  411. exception:out-of-range
  412. (call-with-stack-overflow-handler 1000
  413. trigger-overflow
  414. (lambda () 0)))
  415. (letrec ((fac (lambda (n)
  416. (if (zero? n) 1 (* n (fac (1- n)))))))
  417. (pass-if-equal "overflow handler can allow recursion to continue"
  418. (fac 10)
  419. (call-with-stack-overflow-handler 1
  420. (lambda () (fac 10))
  421. (lambda () 1)))))
  422. ;;;
  423. ;;; docstrings
  424. ;;;
  425. (with-test-prefix "docstrings"
  426. (pass-if-equal "fixed closure"
  427. '("hello" "world")
  428. (map procedure-documentation
  429. (list (eval '(lambda (a b) "hello" (+ a b))
  430. (current-module))
  431. (eval '(lambda (a b) "world" (- a b))
  432. (current-module)))))
  433. (pass-if-equal "fixed closure with many args"
  434. "So many args."
  435. (procedure-documentation
  436. (eval '(lambda (a b c d e f g h i j k)
  437. "So many args."
  438. (+ a b))
  439. (current-module))))
  440. (pass-if-equal "general closure"
  441. "How general."
  442. (procedure-documentation
  443. (eval '(lambda* (a b #:key k #:rest r)
  444. "How general."
  445. (+ a b))
  446. (current-module)))))
  447. ;;;
  448. ;;; local-eval
  449. ;;;
  450. (with-test-prefix "local evaluation"
  451. (pass-if "local-eval"
  452. (let* ((env1 (local-eval '(let ((x 1) (y 2) (z 3))
  453. (define-syntax-rule (foo x) (quote x))
  454. (the-environment))
  455. (current-module)))
  456. (env2 (local-eval '(let ((x 111) (a 'a))
  457. (define-syntax-rule (bar x) (quote x))
  458. (the-environment))
  459. env1)))
  460. (local-eval '(set! x 11) env1)
  461. (local-eval '(set! y 22) env1)
  462. (local-eval '(set! z 33) env2)
  463. (and (equal? (local-eval '(list x y z) env1)
  464. '(11 22 33))
  465. (equal? (local-eval '(list x y z a) env2)
  466. '(111 22 33 a)))))
  467. (pass-if "local-compile"
  468. (let* ((env1 (local-compile '(let ((x 1) (y 2) (z 3))
  469. (define-syntax-rule (foo x) (quote x))
  470. (the-environment))
  471. (current-module)))
  472. (env2 (local-compile '(let ((x 111) (a 'a))
  473. (define-syntax-rule (bar x) (quote x))
  474. (the-environment))
  475. env1)))
  476. (local-compile '(set! x 11) env1)
  477. (local-compile '(set! y 22) env1)
  478. (local-compile '(set! z 33) env2)
  479. (and (equal? (local-compile '(list x y z) env1)
  480. '(11 22 33))
  481. (equal? (local-compile '(list x y z a) env2)
  482. '(111 22 33 a)))))
  483. (pass-if "the-environment within a macro"
  484. (let ((module-a-name '(test module the-environment a))
  485. (module-b-name '(test module the-environment b)))
  486. (let ((module-a (resolve-module module-a-name))
  487. (module-b (resolve-module module-b-name)))
  488. (module-use! module-a (resolve-interface '(guile)))
  489. (module-use! module-a (resolve-interface '(ice-9 local-eval)))
  490. (eval '(begin
  491. (define z 3)
  492. (define-syntax-rule (test)
  493. (let ((x 1) (y 2))
  494. (the-environment))))
  495. module-a)
  496. (module-use! module-b (resolve-interface '(guile)))
  497. (let ((env (local-eval `(let ((x 111) (y 222))
  498. ((@@ ,module-a-name test)))
  499. module-b)))
  500. (equal? (local-eval '(list x y z) env)
  501. '(1 2 3))))))
  502. (pass-if "capture pattern variables"
  503. (let ((env (syntax-case #'(((a 1) (b 2) (c 3))
  504. ((d 4) (e 5) (f 6))) ()
  505. ((((k v) ...) ...) (the-environment)))))
  506. (equal? (syntax->datum (local-eval '#'((k ... v ...) ...) env))
  507. '((a b c 1 2 3) (d e f 4 5 6)))))
  508. (pass-if "mixed primitive-eval, local-eval and local-compile"
  509. (let* ((env1 (primitive-eval '(let ((x 1) (y 2) (z 3))
  510. (define-syntax-rule (foo x) (quote x))
  511. (the-environment))))
  512. (env2 (local-eval '(let ((x 111) (a 'a))
  513. (define-syntax-rule (bar x) (quote x))
  514. (the-environment))
  515. env1))
  516. (env3 (local-compile '(let ((y 222) (b 'b))
  517. (the-environment))
  518. env2)))
  519. (local-eval '(set! x 11) env1)
  520. (local-compile '(set! y 22) env2)
  521. (local-eval '(set! z 33) env2)
  522. (local-compile '(set! a (* y 2)) env3)
  523. (and (equal? (local-compile '(list x y z) env1)
  524. '(11 22 33))
  525. (equal? (local-eval '(list x y z a) env2)
  526. '(111 22 33 444))
  527. (equal? (local-eval '(list x y z a b) env3)
  528. '(111 222 33 444 b))))))
  529. ;;; eval.test ends here