/compiler/tests/test-cases.scm

http://github.com/tonyg/newmoon · Scheme · 443 lines · 394 code · 48 blank · 1 comment · 1 complexity · 4459f8188cc6560b375b5a83a34c4206 MD5 · raw file

  1. ; MzScheme support code.
  2. (define (run-tests)
  3. (define compiler-tests
  4. (make-test-suite "newmoon compiler tests"
  5. (make-test-case
  6. "exceptions capturable using '=>'"
  7. (assert-equal? 2
  8. (try-catch (raise 'foo 1)
  9. ((foo) => (lambda (e)
  10. (+ (car (exception-arguments e))
  11. 1)))
  12. (else => (lambda (e) e)))))
  13. (make-test-case
  14. "exceptions catchable without using '=>'"
  15. (assert-equal? 2
  16. (try-catch (raise 'foo 1)
  17. ((foo) 2)
  18. (else 'other-exception))))
  19. (make-test-case
  20. "missed exceptions capturable using '=>'"
  21. (assert-equal? '(bar 1)
  22. (try-catch (raise 'bar 1)
  23. ((foo) => (lambda (e)
  24. (+ (car (exception-arguments e))
  25. 1)))
  26. (else => (lambda (e) e)))))
  27. (make-test-case
  28. "missed exceptions catchable without using '=>'"
  29. (assert-equal? 2
  30. (try-catch (raise 'foo 1)
  31. ((foo) 2)
  32. (else 'other-exception))))
  33. (make-test-case
  34. "finalizer runs normally"
  35. (assert-equal? #t
  36. (let ((v #f))
  37. (try-catch 1
  38. ((foo) 2)
  39. (else 3)
  40. (finally (set! v #t)))
  41. v)))
  42. (make-test-case
  43. "finalizer runs on expected exception"
  44. (assert-equal? #t
  45. (let ((v #f))
  46. (try-catch (raise 'foo 1)
  47. ((foo) 2)
  48. (else 3)
  49. (finally (set! v #t)))
  50. v)))
  51. (make-test-case
  52. "finalizer runs on unexpected exception with else"
  53. (assert-equal? #t
  54. (let ((v #f))
  55. (try-catch (raise 'bar 1)
  56. ((foo) 2)
  57. (else 3)
  58. (finally (set! v #t)))
  59. v)))
  60. (make-test-case
  61. "flatten-body works"
  62. (assert-equal? '((define a 1)
  63. (define b 2)
  64. (display (+ a b))
  65. (newline)
  66. (define c 3)
  67. (* b c))
  68. (flatten-body '((define a 1)
  69. (begin
  70. (define b 2)
  71. (display (+ a b))
  72. (newline))
  73. (define c 3) ; note: illegal in this position
  74. (* b c)))))
  75. )) ; end of newmoon compiler tests
  76. (define (rt-eval expr)
  77. (bytecode-apply (bytecode-compile expr) '()))
  78. (define (rt-expect result expr)
  79. (assert-equal? result (rt-eval expr)))
  80. (define runtime-tests
  81. (make-test-suite "newmoon runtime tests"
  82. (make-test-case
  83. "quasiquote on lists works"
  84. (rt-expect '(1 (2 0) 3 4 5)
  85. '`(1 (2 ,(- 2 2)) ,(+ 1 2) ,@(list 4 5))))
  86. (make-test-case
  87. "quasiquote on vectors works"
  88. (rt-expect '#(1 #(2 0) 3 4 5)
  89. '`#(1 #(2 ,(- 2 2)) ,(+ 1 2) ,@(list 4 5))))
  90. (make-test-case
  91. "begin is always its own head expression"
  92. (assert-eq? 5
  93. (try-catch (rt-eval '(let ((a +)
  94. (b 1)
  95. (c 2)
  96. (d 3))
  97. (a (begin b c) d)))
  98. (else => (lambda (e) e)))))
  99. (make-test-case
  100. "macros aren't expanded if they're shadowed"
  101. (rt-expect 5
  102. '((lambda (case) (case 2))
  103. (lambda (lambda) (+ lambda 3)))))
  104. (make-test-case
  105. "No Reserved Identifiers"
  106. (rt-expect 5
  107. '((lambda (lambda define) (lambda define define))
  108. (lambda (lambda define) (+ lambda 3)) 2)))
  109. (make-test-case
  110. "formals mustn't contain non-symbol"
  111. (assert-eq? 'got-exception
  112. (try-catch (rt-eval '((lambda (2) 'no-exception) 'dummy))
  113. ((syntax-error) 'got-exception))))
  114. (make-test-case
  115. "varargs formals mustn't be non-symbol"
  116. (assert-eq? 'got-exception
  117. (try-catch (rt-eval '((lambda 2 'no-exception)))
  118. ((syntax-error) 'got-exception))))
  119. (make-test-case
  120. "macros can expand to definitions (outer)"
  121. (begin
  122. (rt-eval '(defmacro test-case-define-outer (v1 v2)
  123. `(begin
  124. (define ,v1 "hello")
  125. (define ,v2 "world"))))
  126. (rt-eval '(test-case-define-outer xx yy))
  127. (rt-expect "helloworld"
  128. '(string-append xx yy))))
  129. (make-test-case
  130. "macros can expand to definitions (inner)"
  131. (begin
  132. (rt-eval '(defmacro test-case-define-inner (v1 v2)
  133. `(begin
  134. (define ,v1 "goodbye")
  135. (define ,v2 "world"))))
  136. (rt-expect "goodbyeworld"
  137. '(let ()
  138. (test-case-define-inner xx yy)
  139. (string-append xx yy)))))
  140. (make-test-case
  141. "r5rs pitfall 1.1"
  142. (rt-expect 0
  143. '(let ((cont #f))
  144. (letrec ((x (call-with-current-continuation
  145. (lambda (c) (set! cont c) 0)))
  146. (y (call-with-current-continuation
  147. (lambda (c) (set! cont c) 0))))
  148. (if cont
  149. (let ((c cont))
  150. (set! cont #f)
  151. (set! x 1)
  152. (set! y 1)
  153. (c 0))
  154. (+ x y))))))
  155. (make-test-case
  156. "r5rs pitfall 1.2"
  157. (rt-expect #t
  158. '(letrec ((x (call-with-current-continuation list))
  159. (y (call-with-current-continuation list)))
  160. (cond ((procedure? x) (x (pair? y)))
  161. ((procedure? y) (y (pair? x))))
  162. (let ((x (car x)) (y (car y)))
  163. (and (call-with-current-continuation x)
  164. (call-with-current-continuation y)
  165. (call-with-current-continuation x))))))
  166. (make-test-case
  167. "r5rs pitfall 1.3"
  168. (rt-expect #t
  169. '(letrec ((x (call-with-current-continuation
  170. (lambda (c)
  171. (list #T c)))))
  172. (if (car x)
  173. ((cadr x) (list #F (lambda () x)))
  174. (eq? x ((cadr x)))))))
  175. (make-test-case
  176. "r5rs pitfall 2.1"
  177. (rt-expect 1
  178. '(call-with-current-continuation (lambda (c) (0 (c 1))))))
  179. (make-test-case
  180. "r5rs pitfall 4.1"
  181. (rt-expect '(x)
  182. '((lambda lambda lambda) 'x)))
  183. (make-test-case
  184. "r5rs pitfall 4.2"
  185. (rt-expect '(1 2 3)
  186. '((lambda (begin) (begin 1 2 3)) (lambda lambda lambda))))
  187. (make-test-case
  188. "r5rs pitfall 4.3"
  189. (rt-expect #f
  190. '(let ((quote -)) (eqv? '1 1))))
  191. (make-test-case
  192. "r5rs pitfall 5.1"
  193. (rt-expect #f
  194. '(eq? #f '())))
  195. (make-test-case
  196. "r5rs pitfall 5.2"
  197. (rt-expect #f
  198. '(eqv? #f '())))
  199. (make-test-case
  200. "r5rs pitfall 5.3"
  201. (rt-expect #f
  202. '(equal? #f '())))
  203. (make-test-case
  204. "r5rs pitfall 6.1"
  205. (rt-expect #f
  206. '(eq? (string->symbol "f") (string->symbol "F"))))
  207. (make-test-case
  208. "r5rs pitfall 7.1"
  209. (rt-expect 28
  210. '(let ()
  211. (define r #f)
  212. (define a #f)
  213. (define b #f)
  214. (define c #f)
  215. (define i 0)
  216. (let ()
  217. (set! r (+ 1 (+ 2 (+ 3 (call-with-current-continuation (lambda (k) (set! a k) 4))))
  218. (+ 5 (+ 6 (call-with-current-continuation (lambda (k) (set! b k) 7))))))
  219. (if (not c)
  220. (set! c a))
  221. (set! i (+ i 1))
  222. (case i
  223. ((1) (a 5))
  224. ((2) (b 8))
  225. ((3) (a 6))
  226. ((4) (c 4)))
  227. r))))
  228. (make-test-case
  229. "r5rs pitfall 7.2"
  230. (rt-expect 28
  231. '(let ()
  232. (define r #f)
  233. (define a #f)
  234. (define b #f)
  235. (define c #f)
  236. (define i 0)
  237. (let ()
  238. (set! r (+ 1
  239. (+ 2 (+ 3 (call-with-current-continuation
  240. (lambda (k) (set! a k) 4))))
  241. (+ 5 (+ 6 (call-with-current-continuation
  242. (lambda (k) (set! b k) 7))))))
  243. (if (not c)
  244. (set! c a))
  245. (set! i (+ i 1))
  246. (case i
  247. ((1) (b 8))
  248. ((2) (a 5))
  249. ((3) (b 7))
  250. ((4) (c 4)))
  251. r))))
  252. (make-test-case
  253. "r5rs pitfall 7.3"
  254. (rt-expect '((-1 4 5 3)
  255. (4 -1 5 3)
  256. (-1 5 4 3)
  257. (5 -1 4 3)
  258. (4 5 -1 3)
  259. (5 4 -1 3))
  260. '(let ((k1 #f)
  261. (k2 #f)
  262. (k3 #f)
  263. (state 0))
  264. (define (identity x) x)
  265. (define (fn)
  266. ((identity (if (= state 0)
  267. (call-with-current-continuation
  268. (lambda (k) (set! k1 k) +))
  269. +))
  270. (identity (if (= state 0)
  271. (call-with-current-continuation
  272. (lambda (k) (set! k2 k) 1))
  273. 1))
  274. (identity (if (= state 0)
  275. (call-with-current-continuation
  276. (lambda (k) (set! k3 k) 2))
  277. 2))))
  278. (define (check states)
  279. (set! state 0)
  280. (let* ((res '())
  281. (r (fn)))
  282. (set! res (cons r res))
  283. (if (null? states)
  284. res
  285. (begin (set! state (car states))
  286. (set! states (cdr states))
  287. (case state
  288. ((1) (k3 4))
  289. ((2) (k2 2))
  290. ((3) (k1 -)))))))
  291. (map check '((1 2 3) (1 3 2) (2 1 3)
  292. (2 3 1) (3 1 2) (3 2 1))))))
  293. (make-test-case
  294. "r5rs pitfall 7.4"
  295. (rt-expect '(10 9 8 7 6 5 4 3 2 1 0)
  296. '(let ((x '())
  297. (y 0))
  298. (call-with-current-continuation
  299. (lambda (escape)
  300. (let* ((yin ((lambda (foo)
  301. (set! x (cons y x))
  302. (if (= y 10)
  303. (escape x)
  304. (begin
  305. (set! y 0)
  306. foo)))
  307. (call-with-current-continuation
  308. (lambda (bar) bar))))
  309. (yang ((lambda (foo)
  310. (set! y (+ y 1))
  311. foo)
  312. (call-with-current-continuation
  313. (lambda (baz) baz)))))
  314. (yin yang)))))))
  315. (make-test-case
  316. "r5rs pitfall 8.1"
  317. (rt-expect -1
  318. '(let - ((n (- 1))) n)))
  319. (make-test-case
  320. "r5rs pitfall 8.2"
  321. (rt-expect '(1 2 3 4 1 2 3 4 5)
  322. '(let ((ls (list 1 2 3 4)))
  323. (append ls ls '(5)))))
  324. (make-test-case
  325. "r5rs pitfall map-style test"
  326. (rt-eval
  327. '(let ((result
  328. (let ()
  329. (define executed-k #f)
  330. (define cont #f)
  331. (define res1 #f)
  332. (define res2 #f)
  333. (set! res1 (map (lambda (x)
  334. (if (= x 0)
  335. (call-with-current-continuation
  336. (lambda (k) (set! cont k) 0))
  337. 0))
  338. '(1 0 2)))
  339. (if (not executed-k)
  340. (begin (set! executed-k #t)
  341. (set! res2 res1)
  342. (cont 1)))
  343. res2)))
  344. (if (equal? result '(0 0 0))
  345. (display "Map is call/cc safe, but probably not tail recursive or inefficient.")
  346. (display "Map is not call/cc safe, but probably tail recursive and efficient."))
  347. (newline))))
  348. (make-test-case
  349. "test cps begin regression bug"
  350. (rt-expect 3
  351. '(let loop () ; implicit begin-with-set!-head here.
  352. (if #t
  353. (let* ((a (+ 1 1))
  354. (b (+ 2 2)))
  355. 3)
  356. 'foo))))
  357. (make-test-case
  358. "argument expr returns twice"
  359. (rt-expect 0
  360. '(let ((cont #f))
  361. (let ((foo (lambda (x y)
  362. (if cont
  363. (let ((c cont))
  364. (set! cont #f)
  365. (set! x 1)
  366. (set! y 1)
  367. (c 0))
  368. (+ x y)))))
  369. (foo (call-with-current-continuation
  370. (lambda (c) (set! cont c) 0))
  371. (call-with-current-continuation
  372. (lambda (c) (set! cont c) 0)))))))
  373. (make-test-case
  374. "cond with no body in a clause returns the test value"
  375. (rt-expect 12
  376. '(cond
  377. ((+ 5 7))
  378. (else 'nothing))))
  379. (make-test-case
  380. "arglist length 0 passed to varargs lambda works okay"
  381. (rt-expect '()
  382. '((lambda x x))))
  383. (make-test-case
  384. "arglist length 1 passed to varargs lambda works okay"
  385. (rt-expect '(a)
  386. '((lambda x x) 'a)))
  387. (make-test-case
  388. "arglist length 2 passed to varargs lambda works okay"
  389. (rt-expect '(a b)
  390. '((lambda x x) 'a 'b)))
  391. )) ; end of newmoon runtime tests
  392. (test/text-ui
  393. (make-test-suite "all newmoon tests"
  394. compiler-tests
  395. runtime-tests)))