tree-il.test 56 KB

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