tree-il.test 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494
  1. ;;;; tree-il.test --- test suite for compiling tree-il -*- scheme -*-
  2. ;;;; Andy Wingo <wingo@pobox.com> --- May 2009
  3. ;;;;
  4. ;;;; Copyright (C) 2009-2014,2018-2021 Free Software Foundation, Inc.
  5. ;;;;
  6. ;;;; This library is free software; you can redistribute it and/or
  7. ;;;; modify it under the terms of the GNU Lesser General Public
  8. ;;;; License as published by the Free Software Foundation; either
  9. ;;;; version 3 of the License, or (at your option) any later version.
  10. ;;;;
  11. ;;;; This library is distributed in the hope that it will be useful,
  12. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. ;;;; Lesser General Public License for more details.
  15. ;;;;
  16. ;;;; You should have received a copy of the GNU Lesser General Public
  17. ;;;; License along with this library; if not, write to the Free Software
  18. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. (define-module (test-suite tree-il)
  20. #:use-module (test-suite lib)
  21. #:use-module (system base compile)
  22. #:use-module (system base pmatch)
  23. #:use-module (system base message)
  24. #:use-module (language tree-il)
  25. #:use-module (language tree-il primitives)
  26. #:use-module (ice-9 match)
  27. #:use-module (ice-9 regex)
  28. #:use-module (srfi srfi-13))
  29. (define-syntax-rule (pass-if-primitives-resolved in expected)
  30. (pass-if (format #f "primitives-resolved in ~s" 'in)
  31. (let* ((module (let ((m (make-module)))
  32. (beautify-user-module! m)
  33. m))
  34. (orig (parse-tree-il 'in))
  35. (resolved (expand-primitives (resolve-primitives orig module))))
  36. (or (equal? (unparse-tree-il resolved) 'expected)
  37. (begin
  38. (format (current-error-port)
  39. "primitive test failed: got ~s, expected ~s"
  40. resolved 'expected)
  41. #f)))))
  42. (define-syntax pass-if-tree-il->scheme
  43. (syntax-rules ()
  44. ((_ in pat)
  45. (assert-scheme->tree-il->scheme in pat #t))
  46. ((_ in pat guard-exp)
  47. (pass-if 'in
  48. (pmatch (tree-il->scheme
  49. (compile 'in #:from 'scheme #:to 'tree-il))
  50. (pat (guard guard-exp) #t)
  51. (_ #f))))))
  52. (with-test-prefix "primitives"
  53. (with-test-prefix "error"
  54. (pass-if-primitives-resolved
  55. (primcall error (const "message"))
  56. (primcall throw (const misc-error) (const #f)
  57. (const "message") (primcall list) (const #f)))
  58. (pass-if-primitives-resolved
  59. (primcall error (const "message") (const 42))
  60. (primcall throw (const misc-error) (const #f)
  61. (const "message ~S") (primcall list (const 42))
  62. (const #f)))
  63. (pass-if-equal "https://bugs.gnu.org/39509"
  64. '(throw 'misc-error #f "~A" (list "message") #f)
  65. (let ((module (make-fresh-user-module)))
  66. (decompile (expand-primitives
  67. (resolve-primitives
  68. (compile '(error ((lambda () "message")))
  69. #:to 'tree-il)
  70. module))
  71. #:from 'tree-il
  72. #:to 'scheme)))
  73. (pass-if-equal "https://bugs.gnu.org/39509 with argument"
  74. '(throw 'misc-error #f "~A ~S" (list "message" 42) #f)
  75. (let ((module (make-fresh-user-module)))
  76. (decompile (expand-primitives
  77. (resolve-primitives
  78. (compile '(error ((lambda () "message")) 42)
  79. #:to 'tree-il)
  80. module))
  81. #:from 'tree-il
  82. #:to 'scheme)))))
  83. (with-test-prefix "tree-il->scheme"
  84. (pass-if-tree-il->scheme
  85. (case-lambda ((a) a) ((b c) (list b c)))
  86. (case-lambda ((,a) ,a1) ((,b ,c) (list ,b1 ,c1)))
  87. (and (eq? a a1) (eq? b b1) (eq? c c1))))
  88. (with-test-prefix "contification"
  89. (pass-if "http://debbugs.gnu.org/9769"
  90. ((compile '(lambda ()
  91. (let ((fail (lambda () #f)))
  92. (let ((test (lambda () (fail))))
  93. (test))
  94. #t))
  95. ;; Prevent inlining. We're testing contificatoin here,
  96. ;; and inlining it will reduce the entire thing to #t.
  97. #:opts '(#:partial-eval? #f)))))
  98. (define (sum . args)
  99. (apply + args))
  100. (with-test-prefix "many args"
  101. (pass-if "call with > 256 args"
  102. (equal? (compile `(1+ (sum ,@(iota 1000)))
  103. #:env (current-module))
  104. (1+ (apply sum (iota 1000)))))
  105. (pass-if "tail call with > 256 args"
  106. (equal? (compile `(sum ,@(iota 1000))
  107. #:env (current-module))
  108. (apply sum (iota 1000)))))
  109. (with-test-prefix "tree-il-fold"
  110. (pass-if "void"
  111. (let ((up 0) (down 0) (mark (list 'mark)))
  112. (and (eq? mark
  113. (tree-il-fold (lambda (x y) (set! down (1+ down)) y)
  114. (lambda (x y) (set! up (1+ up)) y)
  115. mark
  116. (make-void #f)))
  117. (= up 1)
  118. (= down 1))))
  119. (pass-if "lambda and application"
  120. (let* ((ups '()) (downs '())
  121. (result (tree-il-fold (lambda (x y)
  122. (set! downs (cons x downs))
  123. (1+ y))
  124. (lambda (x y)
  125. (set! ups (cons x ups))
  126. (1+ y))
  127. 0
  128. (parse-tree-il
  129. '(lambda ()
  130. (lambda-case
  131. (((x y) #f #f #f () (x1 y1))
  132. (call (toplevel +)
  133. (lexical x x1)
  134. (lexical y y1)))
  135. #f))))))
  136. (define (strip-source x)
  137. (post-order (lambda (x)
  138. (set! (tree-il-src x) #f)
  139. x)
  140. x))
  141. (and (= result 12)
  142. (equal? (map strip-source (list-head (reverse ups) 3))
  143. (list (make-toplevel-ref #f #f '+)
  144. (make-lexical-ref #f 'x 'x1)
  145. (make-lexical-ref #f 'y 'y1)))
  146. (equal? (map strip-source (reverse (list-head downs 3)))
  147. (list (make-toplevel-ref #f #f '+)
  148. (make-lexical-ref #f 'x 'x1)
  149. (make-lexical-ref #f 'y 'y1)))))))
  150. ;;;
  151. ;;; Warnings.
  152. ;;;
  153. ;; Make sure we get English messages.
  154. (when (defined? 'setlocale)
  155. (setlocale LC_ALL "C"))
  156. (define (call-with-warnings thunk)
  157. (let ((port (open-output-string)))
  158. ;; Disable any warnings added by default.
  159. (parameterize ((default-warning-level 0))
  160. (with-fluids ((*current-warning-port* port)
  161. (*current-warning-prefix* ""))
  162. (thunk)))
  163. (let ((warnings (get-output-string port)))
  164. (string-tokenize warnings
  165. (char-set-complement (char-set #\newline))))))
  166. (define %opts-w-unused
  167. '(#:warnings (unused-variable)))
  168. (define %opts-w-unused-toplevel
  169. '(#:warnings (unused-toplevel)))
  170. (define %opts-w-shadowed-toplevel
  171. '(#:warnings (shadowed-toplevel)))
  172. (define %opts-w-unbound
  173. '(#:warnings (unbound-variable)))
  174. (define %opts-w-use-before-definition
  175. '(#:warnings (use-before-definition)))
  176. (define %opts-w-non-idempotent-definition
  177. '(#:warnings (non-idempotent-definition)))
  178. (define %opts-w-arity
  179. '(#:warnings (arity-mismatch)))
  180. (define %opts-w-format
  181. '(#:warnings (format)))
  182. (define %opts-w-duplicate-case-datum
  183. '(#:warnings (duplicate-case-datum)))
  184. (define %opts-w-bad-case-datum
  185. '(#:warnings (bad-case-datum)))
  186. (with-test-prefix "warnings"
  187. (pass-if "unknown warning type"
  188. (let ((w (call-with-warnings
  189. (lambda ()
  190. (compile #t #:opts '(#:warnings (does-not-exist)))))))
  191. (and (= (length w) 1)
  192. (number? (string-contains (car w) "unknown warning")))))
  193. (with-test-prefix "unused-variable"
  194. (pass-if "quiet"
  195. (null? (call-with-warnings
  196. (lambda ()
  197. (compile '(lambda (x y) (+ x y))
  198. #:opts %opts-w-unused)))))
  199. (pass-if "let/unused"
  200. (let ((w (call-with-warnings
  201. (lambda ()
  202. (compile '(lambda (x)
  203. (let ((y (+ x 2)))
  204. x))
  205. #:opts %opts-w-unused)))))
  206. (and (= (length w) 1)
  207. (number? (string-contains (car w) "unused variable `y'")))))
  208. (pass-if "shadowed variable"
  209. (let ((w (call-with-warnings
  210. (lambda ()
  211. (compile '(lambda (x)
  212. (let ((y x))
  213. (let ((y (+ x 2)))
  214. (+ x y))))
  215. #:opts %opts-w-unused)))))
  216. (and (= (length w) 1)
  217. (number? (string-contains (car w) "unused variable `y'")))))
  218. (pass-if "letrec"
  219. (null? (call-with-warnings
  220. (lambda ()
  221. (compile '(lambda ()
  222. (letrec ((x (lambda () (y)))
  223. (y (lambda () (x))))
  224. y))
  225. #:opts %opts-w-unused)))))
  226. (pass-if "unused argument"
  227. ;; Unused arguments should not be reported.
  228. (null? (call-with-warnings
  229. (lambda ()
  230. (compile '(lambda (x y z) #t)
  231. #:opts %opts-w-unused)))))
  232. (pass-if "special variable names"
  233. (null? (call-with-warnings
  234. (lambda ()
  235. (compile '(lambda ()
  236. (let ((_ 'underscore)
  237. (#{gensym name}# 'ignore-me))
  238. #t))
  239. #:to 'cps
  240. #:opts %opts-w-unused))))))
  241. (with-test-prefix "unused-toplevel"
  242. (pass-if "used after definition"
  243. (null? (call-with-warnings
  244. (lambda ()
  245. (let ((in (open-input-string
  246. "(define foo 2) foo")))
  247. (read-and-compile in
  248. #:to 'cps
  249. #:opts %opts-w-unused-toplevel))))))
  250. (pass-if "used before definition"
  251. (null? (call-with-warnings
  252. (lambda ()
  253. (let ((in (open-input-string
  254. "(define (bar) foo) (define foo 2) (bar)")))
  255. (read-and-compile in
  256. #:to 'cps
  257. #:opts %opts-w-unused-toplevel))))))
  258. (pass-if "unused but public"
  259. (let ((in (open-input-string
  260. "(define-module (test-suite tree-il x) #:export (bar))
  261. (define (bar) #t)")))
  262. (null? (call-with-warnings
  263. (lambda ()
  264. (read-and-compile in
  265. #:to 'cps
  266. #:opts %opts-w-unused-toplevel))))))
  267. (pass-if "unused but public (more)"
  268. (let ((in (open-input-string
  269. "(define-module (test-suite tree-il x) #:export (bar))
  270. (define (bar) (baz))
  271. (define (baz) (foo))
  272. (define (foo) #t)")))
  273. (null? (call-with-warnings
  274. (lambda ()
  275. (read-and-compile in
  276. #:to 'cps
  277. #:opts %opts-w-unused-toplevel))))))
  278. (pass-if "unused but define-public"
  279. (null? (call-with-warnings
  280. (lambda ()
  281. (compile '(define-public foo 2)
  282. #:to 'cps
  283. #:opts %opts-w-unused-toplevel)))))
  284. (pass-if "used by macro"
  285. ;; FIXME: See comment about macros at `unused-toplevel-analysis'.
  286. (throw 'unresolved)
  287. (null? (call-with-warnings
  288. (lambda ()
  289. (let ((in (open-input-string
  290. "(define (bar) 'foo)
  291. (define-syntax baz
  292. (syntax-rules () ((_) (bar))))")))
  293. (read-and-compile in
  294. #:to 'cps
  295. #:opts %opts-w-unused-toplevel))))))
  296. (pass-if "unused"
  297. (let ((w (call-with-warnings
  298. (lambda ()
  299. (compile '(define foo 2)
  300. #:to 'cps
  301. #:opts %opts-w-unused-toplevel)))))
  302. (and (= (length w) 1)
  303. (number? (string-contains (car w)
  304. (format #f "top-level variable `~A'"
  305. 'foo))))))
  306. (pass-if "unused recursive"
  307. (let ((w (call-with-warnings
  308. (lambda ()
  309. (compile '(define (foo) (foo))
  310. #:to 'cps
  311. #:opts %opts-w-unused-toplevel)))))
  312. (and (= (length w) 1)
  313. (number? (string-contains (car w)
  314. (format #f "top-level variable `~A'"
  315. 'foo))))))
  316. (pass-if "unused mutually recursive"
  317. (let* ((in (open-input-string
  318. "(define (foo) (bar)) (define (bar) (foo))"))
  319. (w (call-with-warnings
  320. (lambda ()
  321. (read-and-compile in
  322. #:to 'cps
  323. #:opts %opts-w-unused-toplevel)))))
  324. (and (= (length w) 2)
  325. (number? (string-contains (car w)
  326. (format #f "top-level variable `~A'"
  327. 'foo)))
  328. (number? (string-contains (cadr w)
  329. (format #f "top-level variable `~A'"
  330. 'bar))))))
  331. (pass-if "special variable names"
  332. (null? (call-with-warnings
  333. (lambda ()
  334. (compile '(define #{gensym name}# 'ignore-me)
  335. #:to 'cps
  336. #:opts %opts-w-unused-toplevel))))))
  337. (with-test-prefix "shadowed-toplevel"
  338. (pass-if "quiet"
  339. (null? (call-with-warnings
  340. (lambda ()
  341. (let ((in (open-input-string
  342. "(define foo 2) (define bar 3)")))
  343. (read-and-compile in
  344. #:to 'cps
  345. #:opts
  346. %opts-w-shadowed-toplevel))))))
  347. (pass-if "internal define"
  348. (null? (call-with-warnings
  349. (lambda ()
  350. (let ((in (open-input-string
  351. "(define foo 2)
  352. (define (bar x) (define foo (+ x 2)) (* foo x))")))
  353. (read-and-compile in
  354. #:to 'cps
  355. #:opts
  356. %opts-w-shadowed-toplevel))))))
  357. (pass-if "one shadowing definition"
  358. (match (call-with-warnings
  359. (lambda ()
  360. (let ((in (open-input-string
  361. "(define foo 2)\n (define foo 3)")))
  362. (read-and-compile in
  363. #:to 'cps
  364. #:opts
  365. %opts-w-shadowed-toplevel))))
  366. ((message)
  367. (->bool (string-match ":2:2:.*previous.*foo.*:1:0" message)))))
  368. (pass-if "two shadowing definitions"
  369. (match (call-with-warnings
  370. (lambda ()
  371. (let ((in (open-input-string
  372. "(define-public foo 2)\n(define foo 3)
  373. (define (foo x) x)")))
  374. (read-and-compile in
  375. #:to 'cps
  376. #:opts
  377. %opts-w-shadowed-toplevel))))
  378. ((message1 message2)
  379. (->bool
  380. (and (string-match ":2:0:.*previous.*foo.*:1:0" message1)
  381. (string-match ":3:2:.*previous.*foo.*:1:0" message2))))))
  382. (pass-if "define-public"
  383. (match (call-with-warnings
  384. (lambda ()
  385. (let ((in (open-input-string
  386. "(define foo 2)\n(define-public foo 3)")))
  387. (read-and-compile in
  388. #:to 'cps
  389. #:opts
  390. %opts-w-shadowed-toplevel))))
  391. ((message)
  392. (->bool (string-match ":2:0:.*previous.*foo.*:1:0" message)))))
  393. (pass-if "macro"
  394. (match (call-with-warnings
  395. (lambda ()
  396. (let ((in (open-input-string
  397. "(define foo 42)
  398. (define-syntax-rule (defun proc (args ...) body ...)
  399. (define (proc args ...) body ...))
  400. (defun foo (a b c) (+ a b c))")))
  401. (read-and-compile in
  402. #:to 'cps
  403. #:opts
  404. %opts-w-shadowed-toplevel))))
  405. ((message)
  406. (->bool (string-match ":4:2:.*previous.*foo.*:1:0" message))))))
  407. (with-test-prefix "unbound variable"
  408. (pass-if "quiet"
  409. (null? (call-with-warnings
  410. (lambda ()
  411. (compile '+ #:opts %opts-w-unbound)))))
  412. (pass-if "ref"
  413. (let* ((v (gensym))
  414. (w (call-with-warnings
  415. (lambda ()
  416. (compile v
  417. #:to 'cps
  418. #:opts %opts-w-unbound)))))
  419. (and (= (length w) 1)
  420. (number? (string-contains (car w)
  421. (format #f "unbound variable `~A'"
  422. v))))))
  423. (pass-if "set!"
  424. (let* ((v (gensym))
  425. (w (call-with-warnings
  426. (lambda ()
  427. (compile `(set! ,v 7)
  428. #:to 'cps
  429. #:opts %opts-w-unbound)))))
  430. (and (= (length w) 1)
  431. (number? (string-contains (car w)
  432. (format #f "unbound variable `~A'"
  433. v))))))
  434. (pass-if "module-local top-level is visible"
  435. (let ((m (make-module))
  436. (v (gensym)))
  437. (beautify-user-module! m)
  438. (compile `(define ,v 123)
  439. #:env m #:opts %opts-w-unbound)
  440. (null? (call-with-warnings
  441. (lambda ()
  442. (compile v
  443. #:env m
  444. #:to 'cps
  445. #:opts %opts-w-unbound))))))
  446. (pass-if "module-local top-level is visible after"
  447. (let ((m (make-module))
  448. (v (gensym)))
  449. (beautify-user-module! m)
  450. (null? (call-with-warnings
  451. (lambda ()
  452. (let ((in (open-input-string
  453. "(define (f)
  454. (set! chbouib 3))
  455. (define chbouib 5)")))
  456. (read-and-compile in
  457. #:env m
  458. #:opts %opts-w-unbound)))))))
  459. (pass-if "optional arguments are visible"
  460. (null? (call-with-warnings
  461. (lambda ()
  462. (compile '(lambda* (x #:optional y z) (list x y z))
  463. #:opts %opts-w-unbound
  464. #:to 'cps)))))
  465. (pass-if "keyword arguments are visible"
  466. (null? (call-with-warnings
  467. (lambda ()
  468. (compile '(lambda* (x #:key y z) (list x y z))
  469. #:opts %opts-w-unbound
  470. #:to 'cps)))))
  471. (pass-if "GOOPS definitions are visible"
  472. (let ((m (make-module))
  473. (v (gensym)))
  474. (beautify-user-module! m)
  475. (module-use! m (resolve-interface '(oop goops)))
  476. (null? (call-with-warnings
  477. (lambda ()
  478. (let ((in (open-input-string
  479. "(define-class <foo> ()
  480. (bar #:getter foo-bar))
  481. (define z (foo-bar (make <foo>)))")))
  482. (read-and-compile in
  483. #:env m
  484. #:opts %opts-w-unbound))))))))
  485. (with-test-prefix "use-before-definition"
  486. (define-syntax-rule (pass-if-warnings expr pat test)
  487. (pass-if 'expr
  488. (match (call-with-warnings
  489. (lambda ()
  490. (compile 'expr #:to 'cps
  491. #:opts %opts-w-use-before-definition)))
  492. (pat test)
  493. (_ #f))))
  494. (define-syntax-rule (pass-if-no-warnings expr)
  495. (pass-if-warnings expr () #t))
  496. (pass-if-no-warnings
  497. (begin (define x +) x))
  498. (pass-if-warnings
  499. (begin x (define x +))
  500. (w) (number? (string-contains w "`x' used before definition")))
  501. (pass-if-warnings
  502. (begin (set! x 1) (define x +))
  503. (w) (number? (string-contains w "`x' used before definition")))
  504. (pass-if-no-warnings
  505. (begin (lambda () x) (define x +)))
  506. (pass-if-no-warnings
  507. (begin (if (defined? 'x) x) (define x +))))
  508. (with-test-prefix "non-idempotent-definition"
  509. (define-syntax-rule (pass-if-warnings expr pat test)
  510. (pass-if 'expr
  511. (match (call-with-warnings
  512. (lambda ()
  513. (compile 'expr #:to 'cps
  514. #:opts %opts-w-non-idempotent-definition)))
  515. (pat test)
  516. (_ #f))))
  517. (define-syntax-rule (pass-if-no-warnings expr)
  518. (pass-if-warnings expr () #t))
  519. (pass-if-no-warnings
  520. (begin (define - +) (define y -)))
  521. (pass-if-warnings
  522. (begin - (define - +))
  523. (w) (number? (string-contains w "non-idempotent binding for `-'")))
  524. (pass-if-warnings
  525. (begin (define y -) (define - +))
  526. (w) (number? (string-contains w "non-idempotent binding for `-'")))
  527. (pass-if-no-warnings
  528. (begin (lambda () -) (define - +)))
  529. (pass-if-no-warnings
  530. (begin (if (defined? '-) -) (define - +))))
  531. (with-test-prefix "arity mismatch"
  532. (pass-if "quiet"
  533. (null? (call-with-warnings
  534. (lambda ()
  535. (compile '(cons 'a 'b) #:opts %opts-w-arity)))))
  536. (pass-if "direct application"
  537. (let ((w (call-with-warnings
  538. (lambda ()
  539. (compile '((lambda (x y) (or x y)) 1 2 3 4 5)
  540. #:opts %opts-w-arity
  541. #:to 'cps)))))
  542. (and (= (length w) 1)
  543. (number? (string-contains (car w)
  544. "wrong number of arguments to")))))
  545. (pass-if "local"
  546. (let ((w (call-with-warnings
  547. (lambda ()
  548. (compile '(let ((f (lambda (x y) (+ x y))))
  549. (f 2))
  550. #:opts %opts-w-arity
  551. #:to 'cps)))))
  552. (and (= (length w) 1)
  553. (number? (string-contains (car w)
  554. "wrong number of arguments to")))))
  555. (pass-if "global"
  556. (let ((w (call-with-warnings
  557. (lambda ()
  558. (compile '(cons 1 2 3 4)
  559. #:opts %opts-w-arity
  560. #:to 'cps)))))
  561. (and (= (length w) 1)
  562. (number? (string-contains (car w)
  563. "wrong number of arguments to")))))
  564. (pass-if "alias to global"
  565. (let ((w (call-with-warnings
  566. (lambda ()
  567. (compile '(let ((f cons)) (f 1 2 3 4))
  568. #:opts %opts-w-arity
  569. #:to 'cps)))))
  570. (and (= (length w) 1)
  571. (number? (string-contains (car w)
  572. "wrong number of arguments to")))))
  573. (pass-if "alias to lexical to global"
  574. (let ((w (call-with-warnings
  575. (lambda ()
  576. (compile '(let ((f number?))
  577. (let ((g f))
  578. (f 1 2 3 4)))
  579. #:opts %opts-w-arity
  580. #:to 'cps)))))
  581. (and (= (length w) 1)
  582. (number? (string-contains (car w)
  583. "wrong number of arguments to")))))
  584. (pass-if "alias to lexical"
  585. (let ((w (call-with-warnings
  586. (lambda ()
  587. (compile '(let ((f (lambda (x y z) (+ x y z))))
  588. (let ((g f))
  589. (g 1)))
  590. #:opts %opts-w-arity
  591. #:to 'cps)))))
  592. (and (= (length w) 1)
  593. (number? (string-contains (car w)
  594. "wrong number of arguments to")))))
  595. (pass-if "letrec"
  596. (let ((w (call-with-warnings
  597. (lambda ()
  598. (compile '(letrec ((odd? (lambda (x) (even? (1- x))))
  599. (even? (lambda (x)
  600. (or (= 0 x)
  601. (odd?)))))
  602. (odd? 1))
  603. #:opts %opts-w-arity
  604. #:to 'cps)))))
  605. (and (= (length w) 1)
  606. (number? (string-contains (car w)
  607. "wrong number of arguments to")))))
  608. (pass-if "case-lambda"
  609. (null? (call-with-warnings
  610. (lambda ()
  611. (compile '(let ((f (case-lambda
  612. ((x) 1)
  613. ((x y) 2)
  614. ((x y z) 3))))
  615. (list (f 1)
  616. (f 1 2)
  617. (f 1 2 3)))
  618. #:opts %opts-w-arity
  619. #:to 'cps)))))
  620. (pass-if "case-lambda with wrong number of arguments"
  621. (let ((w (call-with-warnings
  622. (lambda ()
  623. (compile '(let ((f (case-lambda
  624. ((x) 1)
  625. ((x y) 2))))
  626. (f 1 2 3))
  627. #:opts %opts-w-arity
  628. #:to 'cps)))))
  629. (and (= (length w) 1)
  630. (number? (string-contains (car w)
  631. "wrong number of arguments to")))))
  632. (pass-if "case-lambda*"
  633. (null? (call-with-warnings
  634. (lambda ()
  635. (compile '(let ((f (case-lambda*
  636. ((x #:optional y) 1)
  637. ((x #:key y) 2)
  638. ((x y #:key z) 3))))
  639. (list (f 1)
  640. (f 1 2)
  641. (f #:y 2)
  642. (f 1 2 #:z 3)))
  643. #:opts %opts-w-arity
  644. #:to 'cps)))))
  645. (pass-if "case-lambda* with wrong arguments"
  646. (let ((w (call-with-warnings
  647. (lambda ()
  648. (compile '(let ((f (case-lambda*
  649. ((x #:optional y) 1)
  650. ((x #:key y) 2)
  651. ((x y #:key z) 3))))
  652. (list (f)
  653. (f 1 #:z 3)))
  654. #:opts %opts-w-arity
  655. #:to 'cps)))))
  656. (and (= (length w) 2)
  657. (null? (filter (lambda (w)
  658. (not
  659. (number?
  660. (string-contains
  661. w "wrong number of arguments to"))))
  662. w)))))
  663. (pass-if "top-level applicable struct"
  664. (null? (call-with-warnings
  665. (lambda ()
  666. (compile '(let ((p current-warning-port))
  667. (p (+ (p) 1))
  668. (p))
  669. #:opts %opts-w-arity
  670. #:to 'cps)))))
  671. (pass-if "top-level applicable struct with wrong arguments"
  672. (let ((w (call-with-warnings
  673. (lambda ()
  674. (compile '(let ((p current-warning-port))
  675. (p 1 2 3))
  676. #:opts %opts-w-arity
  677. #:to 'cps)))))
  678. (and (= (length w) 1)
  679. (number? (string-contains (car w)
  680. "wrong number of arguments to")))))
  681. (pass-if "local toplevel-defines"
  682. (let ((w (call-with-warnings
  683. (lambda ()
  684. (let ((in (open-input-string "
  685. (define (g x) (f x))
  686. (define (f) 1)")))
  687. (read-and-compile in
  688. #:opts %opts-w-arity
  689. #:to 'cps))))))
  690. (and (= (length w) 1)
  691. (number? (string-contains (car w)
  692. "wrong number of arguments to")))))
  693. (pass-if "global toplevel alias"
  694. (let ((w (call-with-warnings
  695. (lambda ()
  696. (let ((in (open-input-string "
  697. (define f cons)
  698. (define (g) (f))")))
  699. (read-and-compile in
  700. #:opts %opts-w-arity
  701. #:to 'cps))))))
  702. (and (= (length w) 1)
  703. (number? (string-contains (car w)
  704. "wrong number of arguments to")))))
  705. (pass-if "local toplevel overrides global"
  706. (null? (call-with-warnings
  707. (lambda ()
  708. (let ((in (open-input-string "
  709. (define (cons) 0)
  710. (define (foo x) (cons))")))
  711. (read-and-compile in
  712. #:opts %opts-w-arity
  713. #:to 'cps))))))
  714. (pass-if "keyword not passed and quiet"
  715. (null? (call-with-warnings
  716. (lambda ()
  717. (compile '(let ((f (lambda* (x #:key y) y)))
  718. (f 2))
  719. #:opts %opts-w-arity
  720. #:to 'cps)))))
  721. (pass-if "keyword passed and quiet"
  722. (null? (call-with-warnings
  723. (lambda ()
  724. (compile '(let ((f (lambda* (x #:key y) y)))
  725. (f 2 #:y 3))
  726. #:opts %opts-w-arity
  727. #:to 'cps)))))
  728. (pass-if "keyword passed to global and quiet"
  729. (null? (call-with-warnings
  730. (lambda ()
  731. (let ((in (open-input-string "
  732. (use-modules (system base compile))
  733. (compile '(+ 2 3) #:env (current-module))")))
  734. (read-and-compile in
  735. #:opts %opts-w-arity
  736. #:to 'cps))))))
  737. (pass-if "extra keyword"
  738. (let ((w (call-with-warnings
  739. (lambda ()
  740. (compile '(let ((f (lambda* (x #:key y) y)))
  741. (f 2 #:Z 3))
  742. #:opts %opts-w-arity
  743. #:to 'cps)))))
  744. (and (= (length w) 1)
  745. (number? (string-contains (car w)
  746. "wrong number of arguments to")))))
  747. (pass-if "extra keywords allowed"
  748. (null? (call-with-warnings
  749. (lambda ()
  750. (compile '(let ((f (lambda* (x #:key y #:allow-other-keys)
  751. y)))
  752. (f 2 #:Z 3))
  753. #:opts %opts-w-arity
  754. #:to 'cps))))))
  755. (with-test-prefix "format"
  756. (pass-if "quiet (no args)"
  757. (null? (call-with-warnings
  758. (lambda ()
  759. (compile '(format #t "hey!")
  760. #:opts %opts-w-format
  761. #:to 'cps)))))
  762. (pass-if "quiet (1 arg)"
  763. (null? (call-with-warnings
  764. (lambda ()
  765. (compile '(format #t "hey ~A!" "you")
  766. #:opts %opts-w-format
  767. #:to 'cps)))))
  768. (pass-if "quiet (2 args)"
  769. (null? (call-with-warnings
  770. (lambda ()
  771. (compile '(format #t "~A ~A!" "hello" "world")
  772. #:opts %opts-w-format
  773. #:to 'cps)))))
  774. (pass-if "wrong port arg"
  775. (let ((w (call-with-warnings
  776. (lambda ()
  777. (compile '(format 10 "foo")
  778. #:opts %opts-w-format
  779. #:to 'cps)))))
  780. (and (= (length w) 1)
  781. (number? (string-contains (car w)
  782. "wrong port argument")))))
  783. (pass-if "non-literal format string"
  784. (let ((w (call-with-warnings
  785. (lambda ()
  786. (compile '(format #f fmt)
  787. #:opts %opts-w-format
  788. #:to 'cps)))))
  789. (and (= (length w) 1)
  790. (number? (string-contains (car w)
  791. "non-literal format string")))))
  792. (pass-if "non-literal format string using gettext"
  793. (null? (call-with-warnings
  794. (lambda ()
  795. (compile '(format #t (gettext "~A ~A!") "hello" "world")
  796. #:opts %opts-w-format
  797. #:to 'cps)))))
  798. (pass-if "non-literal format string using gettext as _"
  799. (null? (call-with-warnings
  800. (lambda ()
  801. (compile '(format #t (G_ "~A ~A!") "hello" "world")
  802. #:opts %opts-w-format
  803. #:to 'cps)))))
  804. (pass-if "non-literal format string using gettext as top-level _"
  805. (null? (call-with-warnings
  806. (lambda ()
  807. (compile '(begin
  808. (define (_ s) (gettext s "my-domain"))
  809. (format #t (G_ "~A ~A!") "hello" "world"))
  810. #:opts %opts-w-format
  811. #:to 'cps)))))
  812. (pass-if "non-literal format string using gettext as module-ref _"
  813. (null? (call-with-warnings
  814. (lambda ()
  815. (compile '(format #t ((@@ (foo) G_) "~A ~A!") "hello" "world")
  816. #:opts %opts-w-format
  817. #:to 'cps)))))
  818. (pass-if "non-literal format string using gettext as lexical _"
  819. (null? (call-with-warnings
  820. (lambda ()
  821. (compile '(let ((_ (lambda (s)
  822. (gettext s "my-domain"))))
  823. (format #t (G_ "~A ~A!") "hello" "world"))
  824. #:opts %opts-w-format
  825. #:to 'cps)))))
  826. (pass-if "non-literal format string using ngettext"
  827. (null? (call-with-warnings
  828. (lambda ()
  829. (compile '(format #t
  830. (ngettext "~a thing" "~a things" n "dom") n)
  831. #:opts %opts-w-format
  832. #:to 'cps)))))
  833. (pass-if "non-literal format string using ngettext as N_"
  834. (null? (call-with-warnings
  835. (lambda ()
  836. (compile '(format #t (N_ "~a thing" "~a things" n) n)
  837. #:opts %opts-w-format
  838. #:to 'cps)))))
  839. (pass-if "non-literal format string with (define _ gettext)"
  840. (null? (call-with-warnings
  841. (lambda ()
  842. (compile '(begin
  843. (define _ gettext)
  844. (define (foo)
  845. (format #t (G_ "~A ~A!") "hello" "world")))
  846. #:opts %opts-w-format
  847. #:to 'cps)))))
  848. (pass-if "wrong format string"
  849. (let ((w (call-with-warnings
  850. (lambda ()
  851. (compile '(format #f 'not-a-string)
  852. #:opts %opts-w-format
  853. #:to 'cps)))))
  854. (and (= (length w) 1)
  855. (number? (string-contains (car w)
  856. "wrong format string")))))
  857. (pass-if "wrong number of args"
  858. (let ((w (call-with-warnings
  859. (lambda ()
  860. (compile '(format "shbweeb")
  861. #:opts %opts-w-format
  862. #:to 'cps)))))
  863. (and (= (length w) 1)
  864. (number? (string-contains (car w)
  865. "wrong number of arguments")))))
  866. (pass-if "~%, ~~, ~&, ~t, ~_, ~!, ~|, ~/, ~q and ~\\n"
  867. (null? (call-with-warnings
  868. (lambda ()
  869. (compile '((@ (ice-9 format) format) some-port
  870. "~&~3_~~ ~\n~12they~% ~!~|~/~q")
  871. #:opts %opts-w-format
  872. #:to 'cps)))))
  873. (pass-if "one missing argument"
  874. (let ((w (call-with-warnings
  875. (lambda ()
  876. (compile '(format some-port "foo ~A~%")
  877. #:opts %opts-w-format
  878. #:to 'cps)))))
  879. (and (= (length w) 1)
  880. (number? (string-contains (car w)
  881. "expected 1, got 0")))))
  882. (pass-if "one missing argument, gettext"
  883. (let ((w (call-with-warnings
  884. (lambda ()
  885. (compile '(format some-port (gettext "foo ~A~%"))
  886. #:opts %opts-w-format
  887. #:to 'cps)))))
  888. (and (= (length w) 1)
  889. (number? (string-contains (car w)
  890. "expected 1, got 0")))))
  891. (pass-if "two missing arguments"
  892. (let ((w (call-with-warnings
  893. (lambda ()
  894. (compile '((@ (ice-9 format) format) #f
  895. "foo ~10,2f and bar ~S~%")
  896. #:opts %opts-w-format
  897. #:to 'cps)))))
  898. (and (= (length w) 1)
  899. (number? (string-contains (car w)
  900. "expected 2, got 0")))))
  901. (pass-if "one given, one missing argument"
  902. (let ((w (call-with-warnings
  903. (lambda ()
  904. (compile '(format #t "foo ~A and ~S~%" hey)
  905. #:opts %opts-w-format
  906. #:to 'cps)))))
  907. (and (= (length w) 1)
  908. (number? (string-contains (car w)
  909. "expected 2, got 1")))))
  910. (pass-if "too many arguments"
  911. (let ((w (call-with-warnings
  912. (lambda ()
  913. (compile '(format #t "foo ~A~%" 1 2)
  914. #:opts %opts-w-format
  915. #:to 'cps)))))
  916. (and (= (length w) 1)
  917. (number? (string-contains (car w)
  918. "expected 1, got 2")))))
  919. (pass-if "~h"
  920. (null? (call-with-warnings
  921. (lambda ()
  922. (compile '((@ (ice-9 format) format) #t
  923. "foo ~h ~a~%" 123.4 'bar)
  924. #:opts %opts-w-format
  925. #:to 'cps)))))
  926. (pass-if "~:h with locale object"
  927. (null? (call-with-warnings
  928. (lambda ()
  929. (compile '((@ (ice-9 format) format) #t
  930. "foo ~:h~%" 123.4 %global-locale)
  931. #:opts %opts-w-format
  932. #:to 'cps)))))
  933. (pass-if "~:h without locale object"
  934. (let ((w (call-with-warnings
  935. (lambda ()
  936. (compile '((@ (ice-9 format) format) #t "foo ~,2:h" 123.4)
  937. #:opts %opts-w-format
  938. #:to 'cps)))))
  939. (and (= (length w) 1)
  940. (number? (string-contains (car w)
  941. "expected 2, got 1")))))
  942. (with-test-prefix "conditionals"
  943. (pass-if "literals"
  944. (null? (call-with-warnings
  945. (lambda ()
  946. (compile '((@ (ice-9 format) format) #f "~A ~[foo~;bar~;baz~;~] ~10,2f"
  947. 'a 1 3.14)
  948. #:opts %opts-w-format
  949. #:to 'cps)))))
  950. (pass-if "literals with selector"
  951. (let ((w (call-with-warnings
  952. (lambda ()
  953. (compile '((@ (ice-9 format) format) #f "~2[foo~;bar~;baz~;~] ~A"
  954. 1 'dont-ignore-me)
  955. #:opts %opts-w-format
  956. #:to 'cps)))))
  957. (and (= (length w) 1)
  958. (number? (string-contains (car w)
  959. "expected 1, got 2")))))
  960. (pass-if "escapes (exact count)"
  961. (let ((w (call-with-warnings
  962. (lambda ()
  963. (compile '((@ (ice-9 format) format) #f "~[~a~;~a~]")
  964. #:opts %opts-w-format
  965. #:to 'cps)))))
  966. (and (= (length w) 1)
  967. (number? (string-contains (car w)
  968. "expected 2, got 0")))))
  969. (pass-if "escapes with selector"
  970. (let ((w (call-with-warnings
  971. (lambda ()
  972. (compile '((@ (ice-9 format) format) #f "~1[chbouib~;~a~]")
  973. #:opts %opts-w-format
  974. #:to 'cps)))))
  975. (and (= (length w) 1)
  976. (number? (string-contains (car w)
  977. "expected 1, got 0")))))
  978. (pass-if "escapes, range"
  979. (let ((w (call-with-warnings
  980. (lambda ()
  981. (compile '((@ (ice-9 format) format) #f "~[chbouib~;~a~;~2*~a~]")
  982. #:opts %opts-w-format
  983. #:to 'cps)))))
  984. (and (= (length w) 1)
  985. (number? (string-contains (car w)
  986. "expected 1 to 4, got 0")))))
  987. (pass-if "@"
  988. (let ((w (call-with-warnings
  989. (lambda ()
  990. (compile '((@ (ice-9 format) format) #f "~@[temperature=~d~]")
  991. #:opts %opts-w-format
  992. #:to 'cps)))))
  993. (and (= (length w) 1)
  994. (number? (string-contains (car w)
  995. "expected 1, got 0")))))
  996. (pass-if "nested"
  997. (let ((w (call-with-warnings
  998. (lambda ()
  999. (compile '((@ (ice-9 format) format) #f "~:[~[hey~;~a~;~va~]~;~3*~]")
  1000. #:opts %opts-w-format
  1001. #:to 'cps)))))
  1002. (and (= (length w) 1)
  1003. (number? (string-contains (car w)
  1004. "expected 2 to 4, got 0")))))
  1005. (pass-if "unterminated"
  1006. (let ((w (call-with-warnings
  1007. (lambda ()
  1008. (compile '((@ (ice-9 format) format) #f "~[unterminated")
  1009. #:opts %opts-w-format
  1010. #:to 'cps)))))
  1011. (and (= (length w) 1)
  1012. (number? (string-contains (car w)
  1013. "unterminated conditional")))))
  1014. (pass-if "unexpected ~;"
  1015. (let ((w (call-with-warnings
  1016. (lambda ()
  1017. (compile '((@ (ice-9 format) format) #f "foo~;bar")
  1018. #:opts %opts-w-format
  1019. #:to 'cps)))))
  1020. (and (= (length w) 1)
  1021. (number? (string-contains (car w)
  1022. "unexpected")))))
  1023. (pass-if "unexpected ~]"
  1024. (let ((w (call-with-warnings
  1025. (lambda ()
  1026. (compile '((@ (ice-9 format) format) #f "foo~]")
  1027. #:opts %opts-w-format
  1028. #:to 'cps)))))
  1029. (and (= (length w) 1)
  1030. (number? (string-contains (car w)
  1031. "unexpected"))))))
  1032. (pass-if "~{...~}"
  1033. (null? (call-with-warnings
  1034. (lambda ()
  1035. (compile '((@ (ice-9 format) format) #f "~A ~{~S~} ~A"
  1036. 'hello '("ladies" "and")
  1037. 'gentlemen)
  1038. #:opts %opts-w-format
  1039. #:to 'cps)))))
  1040. (pass-if "~{...~}, too many args"
  1041. (let ((w (call-with-warnings
  1042. (lambda ()
  1043. (compile '((@ (ice-9 format) format) #f "~{~S~}" 1 2 3)
  1044. #:opts %opts-w-format
  1045. #:to 'cps)))))
  1046. (and (= (length w) 1)
  1047. (number? (string-contains (car w)
  1048. "expected 1, got 3")))))
  1049. (pass-if "~@{...~}"
  1050. (null? (call-with-warnings
  1051. (lambda ()
  1052. (compile '((@ (ice-9 format) format) #f "~@{~S~}" 1 2 3)
  1053. #:opts %opts-w-format
  1054. #:to 'cps)))))
  1055. (pass-if "~@{...~}, too few args"
  1056. (let ((w (call-with-warnings
  1057. (lambda ()
  1058. (compile '((@ (ice-9 format) format) #f "~A ~@{~S~}")
  1059. #:opts %opts-w-format
  1060. #:to 'cps)))))
  1061. (and (= (length w) 1)
  1062. (number? (string-contains (car w)
  1063. "expected at least 1, got 0")))))
  1064. (pass-if "unterminated ~{...~}"
  1065. (let ((w (call-with-warnings
  1066. (lambda ()
  1067. (compile '((@ (ice-9 format) format) #f "~{")
  1068. #:opts %opts-w-format
  1069. #:to 'cps)))))
  1070. (and (= (length w) 1)
  1071. (number? (string-contains (car w)
  1072. "unterminated")))))
  1073. (pass-if "~(...~)"
  1074. (null? (call-with-warnings
  1075. (lambda ()
  1076. (compile '((@ (ice-9 format) format) #f "~:@(~A ~A~)" 'foo 'bar)
  1077. #:opts %opts-w-format
  1078. #:to 'cps)))))
  1079. (pass-if "~v"
  1080. (let ((w (call-with-warnings
  1081. (lambda ()
  1082. (compile '((@ (ice-9 format) format) #f "~v_foo")
  1083. #:opts %opts-w-format
  1084. #:to 'cps)))))
  1085. (and (= (length w) 1)
  1086. (number? (string-contains (car w)
  1087. "expected 1, got 0")))))
  1088. (pass-if "~v:@y"
  1089. (null? (call-with-warnings
  1090. (lambda ()
  1091. (compile '((@ (ice-9 format) format) #f "~v:@y" 1 123)
  1092. #:opts %opts-w-format
  1093. #:to 'cps)))))
  1094. (pass-if "~*"
  1095. (let ((w (call-with-warnings
  1096. (lambda ()
  1097. (compile '((@ (ice-9 format) format) #f "~2*~a" 'a 'b)
  1098. #:opts %opts-w-format
  1099. #:to 'cps)))))
  1100. (and (= (length w) 1)
  1101. (number? (string-contains (car w)
  1102. "expected 3, got 2")))))
  1103. (pass-if "~p"
  1104. (null? (call-with-warnings
  1105. (lambda ()
  1106. (compile '(((@ (ice-9 format) format) #f "thing~p" 2))
  1107. #:opts %opts-w-format
  1108. #:to 'cps)))))
  1109. (pass-if "~p, too few arguments"
  1110. (let ((w (call-with-warnings
  1111. (lambda ()
  1112. (compile '((@ (ice-9 format) format) #f "~p")
  1113. #:opts %opts-w-format
  1114. #:to 'cps)))))
  1115. (and (= (length w) 1)
  1116. (number? (string-contains (car w)
  1117. "expected 1, got 0")))))
  1118. (pass-if "~:p"
  1119. (null? (call-with-warnings
  1120. (lambda ()
  1121. (compile '(((@ (ice-9 format) format) #f "~d thing~:p" 2))
  1122. #:opts %opts-w-format
  1123. #:to 'cps)))))
  1124. (pass-if "~:@p, too many arguments"
  1125. (let ((w (call-with-warnings
  1126. (lambda ()
  1127. (compile '((@ (ice-9 format) format) #f "~d pupp~:@p" 5 5)
  1128. #:opts %opts-w-format
  1129. #:to 'cps)))))
  1130. (and (= (length w) 1)
  1131. (number? (string-contains (car w)
  1132. "expected 1, got 2")))))
  1133. (pass-if "~:@p, too few arguments"
  1134. (let ((w (call-with-warnings
  1135. (lambda ()
  1136. (compile '((@ (ice-9 format) format) #f "pupp~:@p")
  1137. #:opts %opts-w-format
  1138. #:to 'cps)))))
  1139. (and (= (length w) 1)
  1140. (number? (string-contains (car w)
  1141. "expected 1, got 0")))))
  1142. (pass-if "~?"
  1143. (null? (call-with-warnings
  1144. (lambda ()
  1145. (compile '((@ (ice-9 format) format) #f "~?" "~d ~d" '(1 2))
  1146. #:opts %opts-w-format
  1147. #:to 'cps)))))
  1148. (pass-if "~^"
  1149. (null? (call-with-warnings
  1150. (lambda ()
  1151. (compile '((@ (ice-9 format) format) #f "~a ~^ ~a" 0 1)
  1152. #:opts %opts-w-format
  1153. #:to 'cps)))))
  1154. (pass-if "~^, too few args"
  1155. (let ((w (call-with-warnings
  1156. (lambda ()
  1157. (compile '((@ (ice-9 format) format) #f "~a ~^ ~a")
  1158. #:opts %opts-w-format
  1159. #:to 'cps)))))
  1160. (and (= (length w) 1)
  1161. (number? (string-contains (car w)
  1162. "expected at least 1, got 0")))))
  1163. (pass-if "parameters: +,-,#, and '"
  1164. (null? (call-with-warnings
  1165. (lambda ()
  1166. (compile '((@ (ice-9 format) format) some-port
  1167. "~#~ ~,,-2f ~,,+2f ~'A~" 1234 1234)
  1168. #:opts %opts-w-format
  1169. #:to 'cps)))))
  1170. (pass-if "complex 1"
  1171. (let ((w (call-with-warnings
  1172. (lambda ()
  1173. (compile '((@ (ice-9 format) format) #f
  1174. "~4@S ~32S~@[;; ~1{~@?~}~]~@[~61t at ~a~]\n"
  1175. 1 2 3 4 5 6)
  1176. #:opts %opts-w-format
  1177. #:to 'cps)))))
  1178. (and (= (length w) 1)
  1179. (number? (string-contains (car w)
  1180. "expected 4, got 6")))))
  1181. (pass-if "complex 2"
  1182. (let ((w (call-with-warnings
  1183. (lambda ()
  1184. (compile '((@ (ice-9 format) format) #f
  1185. "~:(~A~) Commands~:[~; [abbrev]~]:~2%"
  1186. 1 2 3 4)
  1187. #:opts %opts-w-format
  1188. #:to 'cps)))))
  1189. (and (= (length w) 1)
  1190. (number? (string-contains (car w)
  1191. "expected 2, got 4")))))
  1192. (pass-if "complex 3"
  1193. (let ((w (call-with-warnings
  1194. (lambda ()
  1195. (compile '((@ (ice-9 format) format) #f "~9@a~:[~*~3_~;~3d~] ~v:@y~%")
  1196. #:opts %opts-w-format
  1197. #:to 'cps)))))
  1198. (and (= (length w) 1)
  1199. (number? (string-contains (car w)
  1200. "expected 5, got 0")))))
  1201. (pass-if "ice-9 format"
  1202. (let ((w (call-with-warnings
  1203. (lambda ()
  1204. (let ((in (open-input-string
  1205. "(use-modules ((ice-9 format) #:prefix i9-))
  1206. (i9-format #t \"yo! ~A\" 1 2)")))
  1207. (read-and-compile in
  1208. #:opts %opts-w-format
  1209. #:to 'cps))))))
  1210. (and (= (length w) 1)
  1211. (number? (string-contains (car w)
  1212. "expected 1, got 2")))))
  1213. (pass-if "not format"
  1214. (null? (call-with-warnings
  1215. (lambda ()
  1216. (compile '(let ((format chbouib))
  1217. (format #t "not ~A a format string"))
  1218. #:opts %opts-w-format
  1219. #:to 'cps)))))
  1220. (with-test-prefix "simple-format"
  1221. (pass-if "good"
  1222. (null? (call-with-warnings
  1223. (lambda ()
  1224. (compile '(simple-format #t "foo ~a bar ~s ~%~~" 1 2)
  1225. #:opts %opts-w-format
  1226. #:to 'cps)))))
  1227. (pass-if "wrong number of args"
  1228. (let ((w (call-with-warnings
  1229. (lambda ()
  1230. (compile '(simple-format #t "foo ~a ~s~%" 'one-missing)
  1231. #:opts %opts-w-format
  1232. #:to 'cps)))))
  1233. (and (= (length w) 1)
  1234. (number? (string-contains (car w) "wrong number")))))
  1235. (pass-if "unsupported"
  1236. (let ((w (call-with-warnings
  1237. (lambda ()
  1238. (compile '(simple-format #t "foo ~x~%" 16)
  1239. #:opts %opts-w-format
  1240. #:to 'cps)))))
  1241. (and (= (length w) 1)
  1242. (number? (string-contains (car w) "unsupported format option")))))
  1243. (pass-if "unsupported, gettext"
  1244. (let ((w (call-with-warnings
  1245. (lambda ()
  1246. (compile '(simple-format #t (gettext "foo ~2f~%") 3.14)
  1247. #:opts %opts-w-format
  1248. #:to 'cps)))))
  1249. (and (= (length w) 1)
  1250. (number? (string-contains (car w) "unsupported format option")))))
  1251. (pass-if "unsupported, ngettext"
  1252. (let ((w (call-with-warnings
  1253. (lambda ()
  1254. (compile '(simple-format #t (ngettext "s ~x" "p ~x" x) x)
  1255. #:opts %opts-w-format
  1256. #:to 'cps)))))
  1257. (and (= (length w) 1)
  1258. (number? (string-contains (car w) "unsupported format option")))))))
  1259. (with-test-prefix "duplicate-case-datum"
  1260. (pass-if "quiet"
  1261. (null? (call-with-warnings
  1262. (lambda ()
  1263. (compile '(case x ((1) 'one) ((2) 'two))
  1264. #:opts %opts-w-duplicate-case-datum
  1265. #:to 'cps)))))
  1266. (pass-if "one duplicate"
  1267. (let ((w (call-with-warnings
  1268. (lambda ()
  1269. (compile '(case x
  1270. ((1) 'one)
  1271. ((2) 'two)
  1272. ((1) 'one-again))
  1273. #:opts %opts-w-duplicate-case-datum
  1274. #:to 'cps)))))
  1275. (and (= (length w) 1)
  1276. (number? (string-contains (car w) "duplicate")))))
  1277. (pass-if "one duplicate"
  1278. (let ((w (call-with-warnings
  1279. (lambda ()
  1280. (compile '(case x
  1281. ((1 2 3) 'a)
  1282. ((1) 'one))
  1283. #:opts %opts-w-duplicate-case-datum
  1284. #:to 'cps)))))
  1285. (and (= (length w) 1)
  1286. (number? (string-contains (car w) "duplicate"))))))
  1287. (with-test-prefix "bad-case-datum"
  1288. (pass-if "quiet"
  1289. (null? (call-with-warnings
  1290. (lambda ()
  1291. (compile '(case x ((1) 'one) ((2) 'two))
  1292. #:opts %opts-w-bad-case-datum
  1293. #:to 'cps)))))
  1294. (pass-if "not eqv?"
  1295. (let ((w (call-with-warnings
  1296. (lambda ()
  1297. (compile '(case x
  1298. ((1) 'one)
  1299. (("bad") 'bad))
  1300. #:opts %opts-w-bad-case-datum
  1301. #:to 'cps)))))
  1302. (and (= (length w) 1)
  1303. (number? (string-contains (car w)
  1304. "cannot be meaningfully compared")))))
  1305. (pass-if "one clause element not eqv?"
  1306. (let ((w (call-with-warnings
  1307. (lambda ()
  1308. (compile '(case x
  1309. ((1 (2) 3) 'a))
  1310. #:opts %opts-w-duplicate-case-datum
  1311. #:to 'cps)))))
  1312. (and (= (length w) 1)
  1313. (number? (string-contains (car w)
  1314. "cannot be meaningfully compared")))))))
  1315. ;; Local Variables:
  1316. ;; eval: (put 'pass-if-primitives-resolved 'scheme-indent-function 1)
  1317. ;; eval: (put 'pass-if-tree-il->scheme 'scheme-indent-function 1)
  1318. ;; End: