syntax.test 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197
  1. ;;;; syntax.test --- test suite for Guile's syntactic forms -*- scheme -*-
  2. ;;;;
  3. ;;;; Copyright (C) 2001,2003,2004, 2005, 2006 Free Software Foundation, Inc.
  4. ;;;;
  5. ;;;; This program is free software; you can redistribute it and/or modify
  6. ;;;; it under the terms of the GNU General Public License as published by
  7. ;;;; the Free Software Foundation; either version 2, or (at your option)
  8. ;;;; any later version.
  9. ;;;;
  10. ;;;; This program 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
  13. ;;;; GNU General Public License for more details.
  14. ;;;;
  15. ;;;; You should have received a copy of the GNU General Public License
  16. ;;;; along with this software; see the file COPYING. If not, write to
  17. ;;;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  18. ;;;; Boston, MA 02110-1301 USA
  19. (define-module (test-suite test-syntax)
  20. :use-module (test-suite lib))
  21. (define exception:bad-expression
  22. (cons 'syntax-error "Bad expression"))
  23. (define exception:missing/extra-expr
  24. (cons 'syntax-error "Missing or extra expression"))
  25. (define exception:missing-expr
  26. (cons 'syntax-error "Missing expression"))
  27. (define exception:missing-body-expr
  28. (cons 'syntax-error "Missing body expression"))
  29. (define exception:extra-expr
  30. (cons 'syntax-error "Extra expression"))
  31. (define exception:illegal-empty-combination
  32. (cons 'syntax-error "Illegal empty combination"))
  33. (define exception:bad-bindings
  34. (cons 'syntax-error "Bad bindings"))
  35. (define exception:bad-binding
  36. (cons 'syntax-error "Bad binding"))
  37. (define exception:duplicate-binding
  38. (cons 'syntax-error "Duplicate binding"))
  39. (define exception:bad-body
  40. (cons 'misc-error "^bad body"))
  41. (define exception:bad-formals
  42. (cons 'syntax-error "Bad formals"))
  43. (define exception:bad-formal
  44. (cons 'syntax-error "Bad formal"))
  45. (define exception:duplicate-formal
  46. (cons 'syntax-error "Duplicate formal"))
  47. (define exception:missing-clauses
  48. (cons 'syntax-error "Missing clauses"))
  49. (define exception:misplaced-else-clause
  50. (cons 'syntax-error "Misplaced else clause"))
  51. (define exception:bad-case-clause
  52. (cons 'syntax-error "Bad case clause"))
  53. (define exception:bad-case-labels
  54. (cons 'syntax-error "Bad case labels"))
  55. (define exception:bad-cond-clause
  56. (cons 'syntax-error "Bad cond clause"))
  57. (with-test-prefix "expressions"
  58. (with-test-prefix "Bad argument list"
  59. (pass-if-exception "improper argument list of length 1"
  60. exception:wrong-num-args
  61. (eval '(let ((foo (lambda (x y) #t)))
  62. (foo . 1))
  63. (interaction-environment)))
  64. (pass-if-exception "improper argument list of length 2"
  65. exception:wrong-num-args
  66. (eval '(let ((foo (lambda (x y) #t)))
  67. (foo 1 . 2))
  68. (interaction-environment))))
  69. (with-test-prefix "missing or extra expression"
  70. ;; R5RS says:
  71. ;; *Note:* In many dialects of Lisp, the empty combination, (),
  72. ;; is a legitimate expression. In Scheme, combinations must
  73. ;; have at least one subexpression, so () is not a syntactically
  74. ;; valid expression.
  75. ;; Fixed on 2001-3-3
  76. (pass-if-exception "empty parentheses \"()\""
  77. exception:illegal-empty-combination
  78. (eval '()
  79. (interaction-environment)))))
  80. (with-test-prefix "quote"
  81. #t)
  82. (with-test-prefix "quasiquote"
  83. (with-test-prefix "unquote"
  84. (pass-if "repeated execution"
  85. (let ((foo (let ((i 0)) (lambda () (set! i (+ i 1)) `(,i)))))
  86. (and (equal? (foo) '(1)) (equal? (foo) '(2))))))
  87. (with-test-prefix "unquote-splicing"
  88. (pass-if-exception "extra arguments"
  89. exception:missing/extra-expr
  90. (quasiquote ((unquote-splicing (list 1 2) (list 3 4)))))))
  91. (with-test-prefix "begin"
  92. (pass-if "legal (begin)"
  93. (begin)
  94. #t)
  95. (with-test-prefix "unmemoization"
  96. (pass-if "normal begin"
  97. (let ((foo (lambda () (if (= 1 1) (begin (+ 1) (+ 2))))))
  98. (foo) ; make sure, memoization has been performed
  99. (equal? (procedure-source foo)
  100. '(lambda () (if (= 1 1) (begin (+ 1) (+ 2)))))))
  101. (pass-if "redundant nested begin"
  102. (let ((foo (lambda () (if (= 1 1) (begin (+ 1) (begin (+ 2) (+ 3)))))))
  103. (foo) ; make sure, memoization has been performed
  104. (equal? (procedure-source foo)
  105. '(lambda () (if (= 1 1) (begin (+ 1) (begin (+ 2) (+ 3))))))))
  106. (pass-if "redundant begin at start of body"
  107. (let ((foo (lambda () (begin (+ 1) (+ 2))))) ; should be optimized
  108. (foo) ; make sure, memoization has been performed
  109. (equal? (procedure-source foo)
  110. '(lambda () (begin (+ 1) (+ 2)))))))
  111. (expect-fail-exception "illegal (begin)"
  112. exception:bad-body
  113. (if #t (begin))
  114. #t))
  115. (with-test-prefix "lambda"
  116. (with-test-prefix "unmemoization"
  117. (pass-if "normal lambda"
  118. (let ((foo (lambda () (lambda (x y) (+ x y)))))
  119. ((foo) 1 2) ; make sure, memoization has been performed
  120. (equal? (procedure-source foo)
  121. '(lambda () (lambda (x y) (+ x y))))))
  122. (pass-if "lambda with documentation"
  123. (let ((foo (lambda () (lambda (x y) "docstring" (+ x y)))))
  124. ((foo) 1 2) ; make sure, memoization has been performed
  125. (equal? (procedure-source foo)
  126. '(lambda () (lambda (x y) "docstring" (+ x y)))))))
  127. (with-test-prefix "bad formals"
  128. (pass-if-exception "(lambda)"
  129. exception:missing-expr
  130. (eval '(lambda)
  131. (interaction-environment)))
  132. (pass-if-exception "(lambda . \"foo\")"
  133. exception:bad-expression
  134. (eval '(lambda . "foo")
  135. (interaction-environment)))
  136. (pass-if-exception "(lambda \"foo\")"
  137. exception:missing-expr
  138. (eval '(lambda "foo")
  139. (interaction-environment)))
  140. (pass-if-exception "(lambda \"foo\" #f)"
  141. exception:bad-formals
  142. (eval '(lambda "foo" #f)
  143. (interaction-environment)))
  144. (pass-if-exception "(lambda (x 1) 2)"
  145. exception:bad-formal
  146. (eval '(lambda (x 1) 2)
  147. (interaction-environment)))
  148. (pass-if-exception "(lambda (1 x) 2)"
  149. exception:bad-formal
  150. (eval '(lambda (1 x) 2)
  151. (interaction-environment)))
  152. (pass-if-exception "(lambda (x \"a\") 2)"
  153. exception:bad-formal
  154. (eval '(lambda (x "a") 2)
  155. (interaction-environment)))
  156. (pass-if-exception "(lambda (\"a\" x) 2)"
  157. exception:bad-formal
  158. (eval '(lambda ("a" x) 2)
  159. (interaction-environment))))
  160. (with-test-prefix "duplicate formals"
  161. ;; Fixed on 2001-3-3
  162. (pass-if-exception "(lambda (x x) 1)"
  163. exception:duplicate-formal
  164. (eval '(lambda (x x) 1)
  165. (interaction-environment)))
  166. ;; Fixed on 2001-3-3
  167. (pass-if-exception "(lambda (x x x) 1)"
  168. exception:duplicate-formal
  169. (eval '(lambda (x x x) 1)
  170. (interaction-environment))))
  171. (with-test-prefix "bad body"
  172. (pass-if-exception "(lambda ())"
  173. exception:missing-expr
  174. (eval '(lambda ())
  175. (interaction-environment)))))
  176. (with-test-prefix "let"
  177. (with-test-prefix "unmemoization"
  178. (pass-if "normal let"
  179. (let ((foo (lambda () (let ((i 1) (j 2)) (+ i j)))))
  180. (foo) ; make sure, memoization has been performed
  181. (equal? (procedure-source foo)
  182. '(lambda () (let ((i 1) (j 2)) (+ i j)))))))
  183. (with-test-prefix "bindings"
  184. (pass-if-exception "late binding"
  185. exception:unbound-var
  186. (let ((x 1) (y x)) y)))
  187. (with-test-prefix "bad bindings"
  188. (pass-if-exception "(let)"
  189. exception:missing-expr
  190. (eval '(let)
  191. (interaction-environment)))
  192. (pass-if-exception "(let 1)"
  193. exception:missing-expr
  194. (eval '(let 1)
  195. (interaction-environment)))
  196. (pass-if-exception "(let (x))"
  197. exception:missing-expr
  198. (eval '(let (x))
  199. (interaction-environment)))
  200. (pass-if-exception "(let ((x)))"
  201. exception:missing-expr
  202. (eval '(let ((x)))
  203. (interaction-environment)))
  204. (pass-if-exception "(let (x) 1)"
  205. exception:bad-binding
  206. (eval '(let (x) 1)
  207. (interaction-environment)))
  208. (pass-if-exception "(let ((x)) 3)"
  209. exception:bad-binding
  210. (eval '(let ((x)) 3)
  211. (interaction-environment)))
  212. (pass-if-exception "(let ((x 1) y) x)"
  213. exception:bad-binding
  214. (eval '(let ((x 1) y) x)
  215. (interaction-environment)))
  216. (pass-if-exception "(let ((1 2)) 3)"
  217. exception:bad-variable
  218. (eval '(let ((1 2)) 3)
  219. (interaction-environment))))
  220. (with-test-prefix "duplicate bindings"
  221. (pass-if-exception "(let ((x 1) (x 2)) x)"
  222. exception:duplicate-binding
  223. (eval '(let ((x 1) (x 2)) x)
  224. (interaction-environment))))
  225. (with-test-prefix "bad body"
  226. (pass-if-exception "(let ())"
  227. exception:missing-expr
  228. (eval '(let ())
  229. (interaction-environment)))
  230. (pass-if-exception "(let ((x 1)))"
  231. exception:missing-expr
  232. (eval '(let ((x 1)))
  233. (interaction-environment)))))
  234. (with-test-prefix "named let"
  235. (with-test-prefix "initializers"
  236. (pass-if "evaluated in outer environment"
  237. (let ((f -))
  238. (eqv? (let f ((n (f 1))) n) -1))))
  239. (with-test-prefix "bad bindings"
  240. (pass-if-exception "(let x (y))"
  241. exception:missing-expr
  242. (eval '(let x (y))
  243. (interaction-environment))))
  244. (with-test-prefix "bad body"
  245. (pass-if-exception "(let x ())"
  246. exception:missing-expr
  247. (eval '(let x ())
  248. (interaction-environment)))
  249. (pass-if-exception "(let x ((y 1)))"
  250. exception:missing-expr
  251. (eval '(let x ((y 1)))
  252. (interaction-environment)))))
  253. (with-test-prefix "let*"
  254. (with-test-prefix "unmemoization"
  255. (pass-if "normal let*"
  256. (let ((foo (lambda () (let* ((x 1) (y 2)) (+ x y)))))
  257. (foo) ; make sure, memoization has been performed
  258. (equal? (procedure-source foo)
  259. '(lambda () (let* ((x 1) (y 2)) (+ x y))))))
  260. (pass-if "let* without bindings"
  261. (let ((foo (lambda () (let ((x 1) (y 2))
  262. (let* ()
  263. (and (= x 1) (= y 2)))))))
  264. (foo) ; make sure, memoization has been performed
  265. (equal? (procedure-source foo)
  266. '(lambda () (let ((x 1) (y 2))
  267. (let* ()
  268. (and (= x 1) (= y 2)))))))))
  269. (with-test-prefix "bindings"
  270. (pass-if "(let* ((x 1) (x 2)) ...)"
  271. (let* ((x 1) (x 2))
  272. (= x 2)))
  273. (pass-if "(let* ((x 1) (x x)) ...)"
  274. (let* ((x 1) (x x))
  275. (= x 1)))
  276. (pass-if "(let ((x 1) (y 2)) (let* () ...))"
  277. (let ((x 1) (y 2))
  278. (let* ()
  279. (and (= x 1) (= y 2))))))
  280. (with-test-prefix "bad bindings"
  281. (pass-if-exception "(let*)"
  282. exception:missing-expr
  283. (eval '(let*)
  284. (interaction-environment)))
  285. (pass-if-exception "(let* 1)"
  286. exception:missing-expr
  287. (eval '(let* 1)
  288. (interaction-environment)))
  289. (pass-if-exception "(let* (x))"
  290. exception:missing-expr
  291. (eval '(let* (x))
  292. (interaction-environment)))
  293. (pass-if-exception "(let* (x) 1)"
  294. exception:bad-binding
  295. (eval '(let* (x) 1)
  296. (interaction-environment)))
  297. (pass-if-exception "(let* ((x)) 3)"
  298. exception:bad-binding
  299. (eval '(let* ((x)) 3)
  300. (interaction-environment)))
  301. (pass-if-exception "(let* ((x 1) y) x)"
  302. exception:bad-binding
  303. (eval '(let* ((x 1) y) x)
  304. (interaction-environment)))
  305. (pass-if-exception "(let* x ())"
  306. exception:bad-bindings
  307. (eval '(let* x ())
  308. (interaction-environment)))
  309. (pass-if-exception "(let* x (y))"
  310. exception:bad-bindings
  311. (eval '(let* x (y))
  312. (interaction-environment)))
  313. (pass-if-exception "(let* ((1 2)) 3)"
  314. exception:bad-variable
  315. (eval '(let* ((1 2)) 3)
  316. (interaction-environment))))
  317. (with-test-prefix "bad body"
  318. (pass-if-exception "(let* ())"
  319. exception:missing-expr
  320. (eval '(let* ())
  321. (interaction-environment)))
  322. (pass-if-exception "(let* ((x 1)))"
  323. exception:missing-expr
  324. (eval '(let* ((x 1)))
  325. (interaction-environment)))))
  326. (with-test-prefix "letrec"
  327. (with-test-prefix "unmemoization"
  328. (pass-if "normal letrec"
  329. (let ((foo (lambda () (letrec ((i 1) (j 2)) (+ i j)))))
  330. (foo) ; make sure, memoization has been performed
  331. (equal? (procedure-source foo)
  332. '(lambda () (letrec ((i 1) (j 2)) (+ i j)))))))
  333. (with-test-prefix "bindings"
  334. (pass-if-exception "initial bindings are undefined"
  335. exception:used-before-defined
  336. (let ((x 1))
  337. (letrec ((x 1) (y x)) y))))
  338. (with-test-prefix "bad bindings"
  339. (pass-if-exception "(letrec)"
  340. exception:missing-expr
  341. (eval '(letrec)
  342. (interaction-environment)))
  343. (pass-if-exception "(letrec 1)"
  344. exception:missing-expr
  345. (eval '(letrec 1)
  346. (interaction-environment)))
  347. (pass-if-exception "(letrec (x))"
  348. exception:missing-expr
  349. (eval '(letrec (x))
  350. (interaction-environment)))
  351. (pass-if-exception "(letrec (x) 1)"
  352. exception:bad-binding
  353. (eval '(letrec (x) 1)
  354. (interaction-environment)))
  355. (pass-if-exception "(letrec ((x)) 3)"
  356. exception:bad-binding
  357. (eval '(letrec ((x)) 3)
  358. (interaction-environment)))
  359. (pass-if-exception "(letrec ((x 1) y) x)"
  360. exception:bad-binding
  361. (eval '(letrec ((x 1) y) x)
  362. (interaction-environment)))
  363. (pass-if-exception "(letrec x ())"
  364. exception:bad-bindings
  365. (eval '(letrec x ())
  366. (interaction-environment)))
  367. (pass-if-exception "(letrec x (y))"
  368. exception:bad-bindings
  369. (eval '(letrec x (y))
  370. (interaction-environment)))
  371. (pass-if-exception "(letrec ((1 2)) 3)"
  372. exception:bad-variable
  373. (eval '(letrec ((1 2)) 3)
  374. (interaction-environment))))
  375. (with-test-prefix "duplicate bindings"
  376. (pass-if-exception "(letrec ((x 1) (x 2)) x)"
  377. exception:duplicate-binding
  378. (eval '(letrec ((x 1) (x 2)) x)
  379. (interaction-environment))))
  380. (with-test-prefix "bad body"
  381. (pass-if-exception "(letrec ())"
  382. exception:missing-expr
  383. (eval '(letrec ())
  384. (interaction-environment)))
  385. (pass-if-exception "(letrec ((x 1)))"
  386. exception:missing-expr
  387. (eval '(letrec ((x 1)))
  388. (interaction-environment)))))
  389. (with-test-prefix "if"
  390. (with-test-prefix "unmemoization"
  391. (pass-if "normal if"
  392. (let ((foo (lambda (x) (if x (+ 1) (+ 2)))))
  393. (foo #t) ; make sure, memoization has been performed
  394. (foo #f) ; make sure, memoization has been performed
  395. (equal? (procedure-source foo)
  396. '(lambda (x) (if x (+ 1) (+ 2))))))
  397. (pass-if "if without else"
  398. (let ((foo (lambda (x) (if x (+ 1)))))
  399. (foo #t) ; make sure, memoization has been performed
  400. (foo #f) ; make sure, memoization has been performed
  401. (equal? (procedure-source foo)
  402. '(lambda (x) (if x (+ 1))))))
  403. (pass-if "if #f without else"
  404. (let ((foo (lambda () (if #f #f))))
  405. (foo) ; make sure, memoization has been performed
  406. (equal? (procedure-source foo)
  407. `(lambda () (if #f #f))))))
  408. (with-test-prefix "missing or extra expressions"
  409. (pass-if-exception "(if)"
  410. exception:missing/extra-expr
  411. (eval '(if)
  412. (interaction-environment)))
  413. (pass-if-exception "(if 1 2 3 4)"
  414. exception:missing/extra-expr
  415. (eval '(if 1 2 3 4)
  416. (interaction-environment)))))
  417. (with-test-prefix "cond"
  418. (with-test-prefix "cond is hygienic"
  419. (pass-if "bound 'else is handled correctly"
  420. (eq? (let ((else 'ok)) (cond (else))) 'ok))
  421. (with-test-prefix "bound '=> is handled correctly"
  422. (pass-if "#t => 'ok"
  423. (let ((=> 'foo))
  424. (eq? (cond (#t => 'ok)) 'ok)))
  425. (pass-if "else =>"
  426. (let ((=> 'foo))
  427. (eq? (cond (else =>)) 'foo)))
  428. (pass-if "else => identity"
  429. (let ((=> 'foo))
  430. (eq? (cond (else => identity)) identity)))))
  431. (with-test-prefix "SRFI-61"
  432. (pass-if "always available"
  433. (cond-expand (srfi-61 #t) (else #f)))
  434. (pass-if "single value consequent"
  435. (eq? 'ok (cond (#t identity => (lambda (x) 'ok)) (else #f))))
  436. (pass-if "single value alternate"
  437. (eq? 'ok (cond (#t not => (lambda (x) #f)) (else 'ok))))
  438. (pass-if-exception "doesn't affect standard =>"
  439. exception:wrong-num-args
  440. (cond ((values 1 2) => (lambda (x y) #t))))
  441. (pass-if "multiple values consequent"
  442. (equal? '(2 1) (cond ((values 1 2)
  443. (lambda (one two)
  444. (and (= 1 one) (= 2 two))) =>
  445. (lambda (one two) (list two one)))
  446. (else #f))))
  447. (pass-if "multiple values alternate"
  448. (eq? 'ok (cond ((values 2 3 4)
  449. (lambda args (equal? '(1 2 3) args)) =>
  450. (lambda (x y z) #f))
  451. (else 'ok))))
  452. (pass-if "zero values"
  453. (eq? 'ok (cond ((values) (lambda () #t) => (lambda () 'ok))
  454. (else #f))))
  455. (pass-if "bound => is handled correctly"
  456. (let ((=> 'ok))
  457. (eq? 'ok (cond (#t identity =>) (else #f)))))
  458. (pass-if-exception "missing recipient"
  459. '(syntax-error . "Missing recipient")
  460. (cond (#t identity =>)))
  461. (pass-if-exception "extra recipient"
  462. '(syntax-error . "Extra expression")
  463. (cond (#t identity => identity identity))))
  464. (with-test-prefix "unmemoization"
  465. (pass-if "normal clauses"
  466. (let ((foo (lambda (x) (cond ((= x 1) 'bar) ((= x 2) 'baz)))))
  467. (foo 1) ; make sure, memoization has been performed
  468. (foo 2) ; make sure, memoization has been performed
  469. (equal? (procedure-source foo)
  470. '(lambda (x) (cond ((= x 1) 'bar) ((= x 2) 'baz))))))
  471. (pass-if "else"
  472. (let ((foo (lambda () (cond (else 'bar)))))
  473. (foo) ; make sure, memoization has been performed
  474. (equal? (procedure-source foo)
  475. '(lambda () (cond (else 'bar))))))
  476. (pass-if "=>"
  477. (let ((foo (lambda () (cond (#t => identity)))))
  478. (foo) ; make sure, memoization has been performed
  479. (equal? (procedure-source foo)
  480. '(lambda () (cond (#t => identity)))))))
  481. (with-test-prefix "bad or missing clauses"
  482. (pass-if-exception "(cond)"
  483. exception:missing-clauses
  484. (eval '(cond)
  485. (interaction-environment)))
  486. (pass-if-exception "(cond #t)"
  487. exception:bad-cond-clause
  488. (eval '(cond #t)
  489. (interaction-environment)))
  490. (pass-if-exception "(cond 1)"
  491. exception:bad-cond-clause
  492. (eval '(cond 1)
  493. (interaction-environment)))
  494. (pass-if-exception "(cond 1 2)"
  495. exception:bad-cond-clause
  496. (eval '(cond 1 2)
  497. (interaction-environment)))
  498. (pass-if-exception "(cond 1 2 3)"
  499. exception:bad-cond-clause
  500. (eval '(cond 1 2 3)
  501. (interaction-environment)))
  502. (pass-if-exception "(cond 1 2 3 4)"
  503. exception:bad-cond-clause
  504. (eval '(cond 1 2 3 4)
  505. (interaction-environment)))
  506. (pass-if-exception "(cond ())"
  507. exception:bad-cond-clause
  508. (eval '(cond ())
  509. (interaction-environment)))
  510. (pass-if-exception "(cond () 1)"
  511. exception:bad-cond-clause
  512. (eval '(cond () 1)
  513. (interaction-environment)))
  514. (pass-if-exception "(cond (1) 1)"
  515. exception:bad-cond-clause
  516. (eval '(cond (1) 1)
  517. (interaction-environment))))
  518. (with-test-prefix "wrong number of arguments"
  519. (pass-if-exception "=> (lambda (x y) #t)"
  520. exception:wrong-num-args
  521. (cond (1 => (lambda (x y) #t))))))
  522. (with-test-prefix "case"
  523. (pass-if "clause with empty labels list"
  524. (case 1 (() #f) (else #t)))
  525. (with-test-prefix "case is hygienic"
  526. (pass-if-exception "bound 'else is handled correctly"
  527. exception:bad-case-labels
  528. (eval '(let ((else #f)) (case 1 (else #f)))
  529. (interaction-environment))))
  530. (with-test-prefix "unmemoization"
  531. (pass-if "normal clauses"
  532. (let ((foo (lambda (x) (case x ((1) 'bar) ((2) 'baz) (else 'foobar)))))
  533. (foo 1) ; make sure, memoization has been performed
  534. (foo 2) ; make sure, memoization has been performed
  535. (foo 3) ; make sure, memoization has been performed
  536. (equal? (procedure-source foo)
  537. '(lambda (x) (case x ((1) 'bar) ((2) 'baz) (else 'foobar))))))
  538. (pass-if "empty labels"
  539. (let ((foo (lambda (x) (case x ((1) 'bar) (() 'baz) (else 'foobar)))))
  540. (foo 1) ; make sure, memoization has been performed
  541. (foo 2) ; make sure, memoization has been performed
  542. (foo 3) ; make sure, memoization has been performed
  543. (equal? (procedure-source foo)
  544. '(lambda (x) (case x ((1) 'bar) (() 'baz) (else 'foobar)))))))
  545. (with-test-prefix "bad or missing clauses"
  546. (pass-if-exception "(case)"
  547. exception:missing-clauses
  548. (eval '(case)
  549. (interaction-environment)))
  550. (pass-if-exception "(case . \"foo\")"
  551. exception:bad-expression
  552. (eval '(case . "foo")
  553. (interaction-environment)))
  554. (pass-if-exception "(case 1)"
  555. exception:missing-clauses
  556. (eval '(case 1)
  557. (interaction-environment)))
  558. (pass-if-exception "(case 1 . \"foo\")"
  559. exception:bad-expression
  560. (eval '(case 1 . "foo")
  561. (interaction-environment)))
  562. (pass-if-exception "(case 1 \"foo\")"
  563. exception:bad-case-clause
  564. (eval '(case 1 "foo")
  565. (interaction-environment)))
  566. (pass-if-exception "(case 1 ())"
  567. exception:bad-case-clause
  568. (eval '(case 1 ())
  569. (interaction-environment)))
  570. (pass-if-exception "(case 1 (\"foo\"))"
  571. exception:bad-case-clause
  572. (eval '(case 1 ("foo"))
  573. (interaction-environment)))
  574. (pass-if-exception "(case 1 (\"foo\" \"bar\"))"
  575. exception:bad-case-labels
  576. (eval '(case 1 ("foo" "bar"))
  577. (interaction-environment)))
  578. (pass-if-exception "(case 1 ((2) \"bar\") . \"foo\")"
  579. exception:bad-expression
  580. (eval '(case 1 ((2) "bar") . "foo")
  581. (interaction-environment)))
  582. (pass-if-exception "(case 1 ((2) \"bar\") (else))"
  583. exception:bad-case-clause
  584. (eval '(case 1 ((2) "bar") (else))
  585. (interaction-environment)))
  586. (pass-if-exception "(case 1 (else #f) . \"foo\")"
  587. exception:bad-expression
  588. (eval '(case 1 (else #f) . "foo")
  589. (interaction-environment)))
  590. (pass-if-exception "(case 1 (else #f) ((1) #t))"
  591. exception:misplaced-else-clause
  592. (eval '(case 1 (else #f) ((1) #t))
  593. (interaction-environment)))))
  594. (with-test-prefix "top-level define"
  595. (pass-if "redefinition"
  596. (let ((m (make-module)))
  597. (beautify-user-module! m)
  598. ;; The previous value of `round' must still be visible at the time the
  599. ;; new `round' is defined. According to R5RS (Section 5.2.1), `define'
  600. ;; should behave like `set!' in this case (except that in the case of
  601. ;; Guile, we respect module boundaries).
  602. (eval '(define round round) m)
  603. (eq? (module-ref m 'round) round)))
  604. (with-test-prefix "currying"
  605. (pass-if "(define ((foo)) #f)"
  606. (eval '(begin
  607. (define ((foo)) #t)
  608. ((foo)))
  609. (interaction-environment))))
  610. (with-test-prefix "unmemoization"
  611. (pass-if "definition unmemoized without prior execution"
  612. (eval '(begin
  613. (define (blub) (cons ('(1 . 2)) 2))
  614. (equal?
  615. (procedure-source blub)
  616. '(lambda () (cons ('(1 . 2)) 2))))
  617. (interaction-environment)))
  618. (pass-if "definition with documentation unmemoized without prior execution"
  619. (eval '(begin
  620. (define (blub) "Comment" (cons ('(1 . 2)) 2))
  621. (equal?
  622. (procedure-source blub)
  623. '(lambda () "Comment" (cons ('(1 . 2)) 2))))
  624. (interaction-environment))))
  625. (with-test-prefix "missing or extra expressions"
  626. (pass-if-exception "(define)"
  627. exception:missing-expr
  628. (eval '(define)
  629. (interaction-environment)))))
  630. (with-test-prefix "internal define"
  631. (pass-if "internal defines become letrec"
  632. (eval '(let ((a identity) (b identity) (c identity))
  633. (define (a x) (if (= x 0) 'a (b (- x 1))))
  634. (define (b x) (if (= x 0) 'b (c (- x 1))))
  635. (define (c x) (if (= x 0) 'c (a (- x 1))))
  636. (and (eq? 'a (a 0) (a 3))
  637. (eq? 'b (a 1) (a 4))
  638. (eq? 'c (a 2) (a 5))))
  639. (interaction-environment)))
  640. (pass-if "binding is created before expression is evaluated"
  641. ;; Internal defines are equivalent to `letrec' (R5RS, Section 5.2.2).
  642. (= (eval '(let ()
  643. (define foo
  644. (begin
  645. (set! foo 1)
  646. (+ foo 1)))
  647. foo)
  648. (interaction-environment))
  649. 2))
  650. (pass-if "internal defines with begin"
  651. (false-if-exception
  652. (eval '(let ((a identity) (b identity) (c identity))
  653. (define (a x) (if (= x 0) 'a (b (- x 1))))
  654. (begin
  655. (define (b x) (if (= x 0) 'b (c (- x 1)))))
  656. (define (c x) (if (= x 0) 'c (a (- x 1))))
  657. (and (eq? 'a (a 0) (a 3))
  658. (eq? 'b (a 1) (a 4))
  659. (eq? 'c (a 2) (a 5))))
  660. (interaction-environment))))
  661. (pass-if "internal defines with empty begin"
  662. (false-if-exception
  663. (eval '(let ((a identity) (b identity) (c identity))
  664. (define (a x) (if (= x 0) 'a (b (- x 1))))
  665. (begin)
  666. (define (b x) (if (= x 0) 'b (c (- x 1))))
  667. (define (c x) (if (= x 0) 'c (a (- x 1))))
  668. (and (eq? 'a (a 0) (a 3))
  669. (eq? 'b (a 1) (a 4))
  670. (eq? 'c (a 2) (a 5))))
  671. (interaction-environment))))
  672. (pass-if "internal defines with macro application"
  673. (false-if-exception
  674. (eval '(begin
  675. (defmacro my-define forms
  676. (cons 'define forms))
  677. (let ((a identity) (b identity) (c identity))
  678. (define (a x) (if (= x 0) 'a (b (- x 1))))
  679. (my-define (b x) (if (= x 0) 'b (c (- x 1))))
  680. (define (c x) (if (= x 0) 'c (a (- x 1))))
  681. (and (eq? 'a (a 0) (a 3))
  682. (eq? 'b (a 1) (a 4))
  683. (eq? 'c (a 2) (a 5)))))
  684. (interaction-environment))))
  685. (pass-if-exception "missing body expression"
  686. exception:missing-body-expr
  687. (eval '(let () (define x #t))
  688. (interaction-environment)))
  689. (pass-if "unmemoization"
  690. (eval '(begin
  691. (define (foo)
  692. (define (bar)
  693. 'ok)
  694. (bar))
  695. (foo)
  696. (equal?
  697. (procedure-source foo)
  698. '(lambda () (letrec ((bar (lambda () (quote ok)))) (bar)))))
  699. (interaction-environment))))
  700. (with-test-prefix "do"
  701. (with-test-prefix "unmemoization"
  702. (pass-if "normal case"
  703. (let ((foo (lambda () (do ((i 1 (+ i 1)) (j 2))
  704. ((> i 9) (+ i j))
  705. (identity i)))))
  706. (foo) ; make sure, memoization has been performed
  707. (equal? (procedure-source foo)
  708. '(lambda () (do ((i 1 (+ i 1)) (j 2))
  709. ((> i 9) (+ i j))
  710. (identity i))))))
  711. (pass-if "reduced case"
  712. (let ((foo (lambda () (do ((i 1 (+ i 1)) (j 2 j)) ; redundant step for j
  713. ((> i 9) (+ i j))
  714. (identity i)))))
  715. (foo) ; make sure, memoization has been performed
  716. (equal? (procedure-source foo)
  717. '(lambda () (do ((i 1 (+ i 1)) (j 2)) ; no redundancy here
  718. ((> i 9) (+ i j))
  719. (identity i))))))))
  720. (with-test-prefix "set!"
  721. (with-test-prefix "unmemoization"
  722. (pass-if "normal set!"
  723. (let ((foo (lambda (x) (set! x (+ 1 x)))))
  724. (foo 1) ; make sure, memoization has been performed
  725. (equal? (procedure-source foo)
  726. '(lambda (x) (set! x (+ 1 x)))))))
  727. (with-test-prefix "missing or extra expressions"
  728. (pass-if-exception "(set!)"
  729. exception:missing/extra-expr
  730. (eval '(set!)
  731. (interaction-environment)))
  732. (pass-if-exception "(set! 1)"
  733. exception:missing/extra-expr
  734. (eval '(set! 1)
  735. (interaction-environment)))
  736. (pass-if-exception "(set! 1 2 3)"
  737. exception:missing/extra-expr
  738. (eval '(set! 1 2 3)
  739. (interaction-environment))))
  740. (with-test-prefix "bad variable"
  741. (pass-if-exception "(set! \"\" #t)"
  742. exception:bad-variable
  743. (eval '(set! "" #t)
  744. (interaction-environment)))
  745. (pass-if-exception "(set! 1 #t)"
  746. exception:bad-variable
  747. (eval '(set! 1 #t)
  748. (interaction-environment)))
  749. (pass-if-exception "(set! #t #f)"
  750. exception:bad-variable
  751. (eval '(set! #t #f)
  752. (interaction-environment)))
  753. (pass-if-exception "(set! #f #t)"
  754. exception:bad-variable
  755. (eval '(set! #f #t)
  756. (interaction-environment)))
  757. (pass-if-exception "(set! #\\space #f)"
  758. exception:bad-variable
  759. (eval '(set! #\space #f)
  760. (interaction-environment)))))
  761. (with-test-prefix "quote"
  762. (with-test-prefix "missing or extra expression"
  763. (pass-if-exception "(quote)"
  764. exception:missing/extra-expr
  765. (eval '(quote)
  766. (interaction-environment)))
  767. (pass-if-exception "(quote a b)"
  768. exception:missing/extra-expr
  769. (eval '(quote a b)
  770. (interaction-environment)))))
  771. (with-test-prefix "while"
  772. (define (unreachable)
  773. (error "unreachable code has been reached!"))
  774. ;; Return a new procedure COND which when called (COND) will return #t the
  775. ;; first N times, then #f, then any further call is an error. N=0 is
  776. ;; allowed, in which case #f is returned by the first call.
  777. (define (make-iterations-cond n)
  778. (lambda ()
  779. (cond ((not n)
  780. (error "oops, condition re-tested after giving false"))
  781. ((= 0 n)
  782. (set! n #f)
  783. #f)
  784. (else
  785. (set! n (1- n))
  786. #t))))
  787. (pass-if-exception "too few args" exception:wrong-num-args
  788. (eval '(while) (interaction-environment)))
  789. (with-test-prefix "empty body"
  790. (do ((n 0 (1+ n)))
  791. ((> n 5))
  792. (pass-if n
  793. (let ((cond (make-iterations-cond n)))
  794. (while (cond)))
  795. #t)))
  796. (pass-if "initially false"
  797. (while #f
  798. (unreachable))
  799. #t)
  800. (with-test-prefix "in empty environment"
  801. ;; an environment with no bindings at all
  802. (define empty-environment
  803. (make-module 1))
  804. ;; these tests are 'unresolved because to work with ice-9 syncase it was
  805. ;; necessary to drop the unquote from `do' in the implementation, and
  806. ;; unfortunately that makes `while' depend on its evaluation environment
  807. (pass-if "empty body"
  808. (throw 'unresolved)
  809. (eval `(,while #f)
  810. empty-environment)
  811. #t)
  812. (pass-if "initially false"
  813. (throw 'unresolved)
  814. (eval `(,while #f
  815. #f)
  816. empty-environment)
  817. #t)
  818. (pass-if "iterating"
  819. (throw 'unresolved)
  820. (let ((cond (make-iterations-cond 3)))
  821. (eval `(,while (,cond)
  822. 123 456)
  823. empty-environment))
  824. #t))
  825. (with-test-prefix "iterations"
  826. (do ((n 0 (1+ n)))
  827. ((> n 5))
  828. (pass-if n
  829. (let ((cond (make-iterations-cond n))
  830. (i 0))
  831. (while (cond)
  832. (set! i (1+ i)))
  833. (= i n)))))
  834. (with-test-prefix "break"
  835. (pass-if-exception "too many args" exception:wrong-num-args
  836. (while #t
  837. (break 1)))
  838. (with-test-prefix "from cond"
  839. (pass-if "first"
  840. (while (begin
  841. (break)
  842. (unreachable))
  843. (unreachable))
  844. #t)
  845. (do ((n 0 (1+ n)))
  846. ((> n 5))
  847. (pass-if n
  848. (let ((cond (make-iterations-cond n))
  849. (i 0))
  850. (while (if (cond)
  851. #t
  852. (begin
  853. (break)
  854. (unreachable)))
  855. (set! i (1+ i)))
  856. (= i n)))))
  857. (with-test-prefix "from body"
  858. (pass-if "first"
  859. (while #t
  860. (break)
  861. (unreachable))
  862. #t)
  863. (do ((n 0 (1+ n)))
  864. ((> n 5))
  865. (pass-if n
  866. (let ((cond (make-iterations-cond n))
  867. (i 0))
  868. (while #t
  869. (if (not (cond))
  870. (begin
  871. (break)
  872. (unreachable)))
  873. (set! i (1+ i)))
  874. (= i n)))))
  875. (pass-if "from nested"
  876. (while #t
  877. (let ((outer-break break))
  878. (while #t
  879. (outer-break)
  880. (unreachable)))
  881. (unreachable))
  882. #t)
  883. (pass-if "from recursive"
  884. (let ((outer-break #f))
  885. (define (r n)
  886. (while #t
  887. (if (eq? n 'outer)
  888. (begin
  889. (set! outer-break break)
  890. (r 'inner))
  891. (begin
  892. (outer-break)
  893. (unreachable))))
  894. (if (eq? n 'inner)
  895. (error "broke only from inner loop")))
  896. (r 'outer))
  897. #t))
  898. (with-test-prefix "continue"
  899. (pass-if-exception "too many args" exception:wrong-num-args
  900. (while #t
  901. (continue 1)))
  902. (with-test-prefix "from cond"
  903. (do ((n 0 (1+ n)))
  904. ((> n 5))
  905. (pass-if n
  906. (let ((cond (make-iterations-cond n))
  907. (i 0))
  908. (while (if (cond)
  909. (begin
  910. (set! i (1+ i))
  911. (continue)
  912. (unreachable))
  913. #f)
  914. (unreachable))
  915. (= i n)))))
  916. (with-test-prefix "from body"
  917. (do ((n 0 (1+ n)))
  918. ((> n 5))
  919. (pass-if n
  920. (let ((cond (make-iterations-cond n))
  921. (i 0))
  922. (while (cond)
  923. (set! i (1+ i))
  924. (continue)
  925. (unreachable))
  926. (= i n)))))
  927. (pass-if "from nested"
  928. (let ((cond (make-iterations-cond 3)))
  929. (while (cond)
  930. (let ((outer-continue continue))
  931. (while #t
  932. (outer-continue)
  933. (unreachable)))))
  934. #t)
  935. (pass-if "from recursive"
  936. (let ((outer-continue #f))
  937. (define (r n)
  938. (let ((cond (make-iterations-cond 3))
  939. (first #t))
  940. (while (begin
  941. (if (and (not first)
  942. (eq? n 'inner))
  943. (error "continued only to inner loop"))
  944. (cond))
  945. (set! first #f)
  946. (if (eq? n 'outer)
  947. (begin
  948. (set! outer-continue continue)
  949. (r 'inner))
  950. (begin
  951. (outer-continue)
  952. (unreachable))))))
  953. (r 'outer))
  954. #t)))