eval.test 19 KB

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