GOOPS cosmetics
[bpt/guile.git] / test-suite / tests / rtl.test
CommitLineData
691697de 1;;;; Low-level tests of the bytecode assembler -*- mode: scheme; coding: utf-8; -*-
e78991aa 2;;;;
4cbe4d72 3;;;; Copyright (C) 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
e78991aa
AW
4;;;;
5;;;; This library is free software; you can redistribute it and/or
6;;;; modify it under the terms of the GNU Lesser General Public
7;;;; License as published by the Free Software Foundation; either
8;;;; version 3 of the License, or (at your option) any later version.
9;;;;
10;;;; This library is distributed in the hope that it will be useful,
11;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13;;;; Lesser General Public License for more details.
14;;;;
15;;;; You should have received a copy of the GNU Lesser General Public
16;;;; License along with this library; if not, write to the Free Software
17;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
691697de 19(define-module (tests bytecode)
e78991aa 20 #:use-module (test-suite lib)
cb86cbd7
AW
21 #:use-module (system vm assembler)
22 #:use-module (system vm program)
4cbc95f1 23 #:use-module (system vm loader)
4dfae1bf 24 #:use-module (system vm linker)
cb86cbd7 25 #:use-module (system vm debug))
e78991aa 26
4dfae1bf
AW
27(define (assemble-program instructions)
28 "Take the sequence of instructions @var{instructions}, assemble them
691697de 29into bytecode, link an image, and load that image from memory. Returns
4dfae1bf
AW
30a procedure."
31 (let ((asm (make-assembler)))
32 (emit-text asm instructions)
33 (load-thunk-from-memory (link-assembly asm #:page-aligned? #f))))
34
e78991aa
AW
35(define-syntax-rule (assert-equal val expr)
36 (let ((x val))
37 (pass-if (object->string x) (equal? expr x))))
38
39(define (return-constant val)
2a4daafd
AW
40 (assemble-program `((begin-program foo
41 ((name . foo)))
7396d216
AW
42 (begin-standard-arity () 2 #f)
43 (load-constant 1 ,val)
44 (return 1)
3185c907 45 (end-arity)
e78991aa
AW
46 (end-program))))
47
48(define-syntax-rule (assert-constants val ...)
49 (begin
50 (assert-equal val ((return-constant val)))
51 ...))
52
53(with-test-prefix "load-constant"
54 (assert-constants
55 1
56 -1
57 0
58 most-positive-fixnum
59 most-negative-fixnum
60 #t
61 #\c
62 (integer->char 16000)
63 3.14
64 "foo"
65 'foo
66 #:foo
67 "æ" ;; a non-ASCII Latin-1 string
68 "λ" ;; non-ascii, non-latin-1
69 '(1 . 2)
70 '(1 2 3 4)
71 #(1 2 3)
72 #("foo" "bar" 'baz)
7bfbc7b1
AW
73 #vu8()
74 #vu8(1 2 3 4 128 129 130)
75 #u32()
76 #u32(1 2 3 4 128 129 130 255 1000)
77 ;; FIXME: Add more tests for arrays (uniform and otherwise)
e78991aa
AW
78 ))
79
80(with-test-prefix "static procedure"
81 (assert-equal 42
2a4daafd
AW
82 (((assemble-program `((begin-program foo
83 ((name . foo)))
7396d216
AW
84 (begin-standard-arity () 2 #f)
85 (load-static-procedure 1 bar)
86 (return 1)
3185c907 87 (end-arity)
e78991aa 88 (end-program)
2a4daafd
AW
89 (begin-program bar
90 ((name . bar)))
7396d216
AW
91 (begin-standard-arity () 2 #f)
92 (load-constant 1 42)
93 (return 1)
3185c907 94 (end-arity)
e78991aa
AW
95 (end-program)))))))
96
97(with-test-prefix "loop"
98 (assert-equal (* 999 500)
99 (let ((sumto
100 (assemble-program
101 ;; 0: limit
102 ;; 1: n
103 ;; 2: accum
2a4daafd
AW
104 '((begin-program countdown
105 ((name . countdown)))
7396d216 106 (begin-standard-arity (x) 4 #f)
4cbe4d72 107 (definition x 1)
e78991aa
AW
108 (br fix-body)
109 (label loop-head)
af95414f 110 (br-if-= 2 1 #f out)
7396d216
AW
111 (add 3 2 3)
112 (add1 2 2)
e78991aa
AW
113 (br loop-head)
114 (label fix-body)
e78991aa 115 (load-constant 2 0)
7396d216 116 (load-constant 3 0)
e78991aa
AW
117 (br loop-head)
118 (label out)
7396d216 119 (return 3)
3185c907 120 (end-arity)
e78991aa
AW
121 (end-program)))))
122 (sumto 1000))))
123
124(with-test-prefix "accum"
125 (assert-equal (+ 1 2 3)
126 (let ((make-accum
127 (assemble-program
128 ;; 0: elt
129 ;; 1: tail
130 ;; 2: head
2a4daafd
AW
131 '((begin-program make-accum
132 ((name . make-accum)))
7396d216
AW
133 (begin-standard-arity () 3 #f)
134 (load-constant 1 0)
135 (box 1 1)
136 (make-closure 2 accum 1)
137 (free-set! 2 1 0)
138 (return 2)
3185c907 139 (end-arity)
e78991aa 140 (end-program)
2a4daafd
AW
141 (begin-program accum
142 ((name . accum)))
7396d216 143 (begin-standard-arity (x) 4 #f)
4cbe4d72 144 (definition x 1)
7396d216
AW
145 (free-ref 2 0 0)
146 (box-ref 3 2)
147 (add 3 3 1)
148 (box-set! 2 3)
149 (return 3)
3185c907 150 (end-arity)
e78991aa
AW
151 (end-program)))))
152 (let ((accum (make-accum)))
153 (accum 1)
154 (accum 2)
155 (accum 3)))))
156
157(with-test-prefix "call"
158 (assert-equal 42
159 (let ((call ;; (lambda (x) (x))
160 (assemble-program
2a4daafd
AW
161 '((begin-program call
162 ((name . call)))
af95414f 163 (begin-standard-arity (f) 7 #f)
4cbe4d72 164 (definition f 1)
286a0fb3 165 (mov 5 1)
af95414f
AW
166 (call 5 1)
167 (receive 2 5 7)
168 (return 2)
3185c907 169 (end-arity)
e78991aa
AW
170 (end-program)))))
171 (call (lambda () 42))))
172
173 (assert-equal 6
174 (let ((call-with-3 ;; (lambda (x) (x 3))
175 (assemble-program
2a4daafd
AW
176 '((begin-program call-with-3
177 ((name . call-with-3)))
af95414f 178 (begin-standard-arity (f) 7 #f)
4cbe4d72 179 (definition f 1)
286a0fb3
AW
180 (mov 5 1)
181 (load-constant 6 3)
af95414f
AW
182 (call 5 2)
183 (receive 2 5 7)
184 (return 2)
3185c907 185 (end-arity)
e78991aa
AW
186 (end-program)))))
187 (call-with-3 (lambda (x) (* x 2))))))
188
189(with-test-prefix "tail-call"
190 (assert-equal 3
191 (let ((call ;; (lambda (x) (x))
192 (assemble-program
2a4daafd
AW
193 '((begin-program call
194 ((name . call)))
7396d216 195 (begin-standard-arity (f) 2 #f)
4cbe4d72 196 (definition f 1)
af95414f
AW
197 (mov 0 1)
198 (tail-call 1)
3185c907 199 (end-arity)
e78991aa
AW
200 (end-program)))))
201 (call (lambda () 3))))
202
203 (assert-equal 6
204 (let ((call-with-3 ;; (lambda (x) (x 3))
205 (assemble-program
2a4daafd
AW
206 '((begin-program call-with-3
207 ((name . call-with-3)))
af95414f 208 (begin-standard-arity (f) 2 #f)
4cbe4d72 209 (definition f 1)
af95414f
AW
210 (mov 0 1) ;; R0 <- R1
211 (load-constant 1 3) ;; R1 <- 3
212 (tail-call 2)
3185c907 213 (end-arity)
e78991aa
AW
214 (end-program)))))
215 (call-with-3 (lambda (x) (* x 2))))))
216
217(with-test-prefix "cached-toplevel-ref"
218 (assert-equal 5.0
219 (let ((get-sqrt-trampoline
220 (assemble-program
2a4daafd
AW
221 '((begin-program get-sqrt-trampoline
222 ((name . get-sqrt-trampoline)))
7396d216 223 (begin-standard-arity () 2 #f)
af95414f 224 (current-module 1)
7396d216
AW
225 (cache-current-module! 1 sqrt-scope)
226 (load-static-procedure 1 sqrt-trampoline)
227 (return 1)
3185c907 228 (end-arity)
e78991aa
AW
229 (end-program)
230
2a4daafd
AW
231 (begin-program sqrt-trampoline
232 ((name . sqrt-trampoline)))
7396d216 233 (begin-standard-arity (x) 3 #f)
4cbe4d72 234 (definition x 1)
af95414f
AW
235 (cached-toplevel-box 2 sqrt-scope sqrt #t)
236 (box-ref 0 2)
237 (tail-call 2)
3185c907 238 (end-arity)
e78991aa
AW
239 (end-program)))))
240 ((get-sqrt-trampoline) 25.0))))
241
242(define *top-val* 0)
243
244(with-test-prefix "cached-toplevel-set!"
245 (let ((prev *top-val*))
246 (assert-equal (1+ prev)
247 (let ((make-top-incrementor
248 (assemble-program
2a4daafd
AW
249 '((begin-program make-top-incrementor
250 ((name . make-top-incrementor)))
7396d216 251 (begin-standard-arity () 2 #f)
af95414f 252 (current-module 1)
7396d216
AW
253 (cache-current-module! 1 top-incrementor)
254 (load-static-procedure 1 top-incrementor)
255 (return 1)
3185c907 256 (end-arity)
e78991aa
AW
257 (end-program)
258
2a4daafd
AW
259 (begin-program top-incrementor
260 ((name . top-incrementor)))
af95414f
AW
261 (begin-standard-arity () 3 #f)
262 (cached-toplevel-box 1 top-incrementor *top-val* #t)
263 (box-ref 2 1)
264 (add1 2 2)
265 (box-set! 1 2)
84cc4127
MW
266 (reset-frame 1)
267 (return-values)
3185c907 268 (end-arity)
e78991aa
AW
269 (end-program)))))
270 ((make-top-incrementor))
271 *top-val*))))
272
273(with-test-prefix "cached-module-ref"
274 (assert-equal 5.0
275 (let ((get-sqrt-trampoline
276 (assemble-program
2a4daafd
AW
277 '((begin-program get-sqrt-trampoline
278 ((name . get-sqrt-trampoline)))
7396d216
AW
279 (begin-standard-arity () 2 #f)
280 (load-static-procedure 1 sqrt-trampoline)
281 (return 1)
3185c907 282 (end-arity)
e78991aa
AW
283 (end-program)
284
2a4daafd
AW
285 (begin-program sqrt-trampoline
286 ((name . sqrt-trampoline)))
7396d216 287 (begin-standard-arity (x) 3 #f)
4cbe4d72 288 (definition x 1)
af95414f
AW
289 (cached-module-box 2 (guile) sqrt #t #t)
290 (box-ref 0 2)
291 (tail-call 2)
3185c907 292 (end-arity)
e78991aa
AW
293 (end-program)))))
294 ((get-sqrt-trampoline) 25.0))))
295
296(with-test-prefix "cached-module-set!"
297 (let ((prev *top-val*))
298 (assert-equal (1+ prev)
299 (let ((make-top-incrementor
300 (assemble-program
2a4daafd
AW
301 '((begin-program make-top-incrementor
302 ((name . make-top-incrementor)))
7396d216
AW
303 (begin-standard-arity () 2 #f)
304 (load-static-procedure 1 top-incrementor)
305 (return 1)
3185c907 306 (end-arity)
e78991aa
AW
307 (end-program)
308
2a4daafd
AW
309 (begin-program top-incrementor
310 ((name . top-incrementor)))
af95414f 311 (begin-standard-arity () 3 #f)
691697de 312 (cached-module-box 1 (tests bytecode) *top-val* #f #t)
af95414f
AW
313 (box-ref 2 1)
314 (add1 2 2)
315 (box-set! 1 2)
316 (return 2)
3185c907 317 (end-arity)
e78991aa
AW
318 (end-program)))))
319 ((make-top-incrementor))
320 *top-val*))))
cb86cbd7
AW
321
322(with-test-prefix "debug contexts"
323 (let ((return-3 (assemble-program
2a4daafd 324 '((begin-program return-3 ((name . return-3)))
7396d216
AW
325 (begin-standard-arity () 2 #f)
326 (load-constant 1 3)
327 (return 1)
3185c907 328 (end-arity)
cb86cbd7
AW
329 (end-program)))))
330 (pass-if "program name"
d1100525 331 (and=> (find-program-debug-info (program-code return-3))
cb86cbd7
AW
332 (lambda (pdi)
333 (equal? (program-debug-info-name pdi)
334 'return-3))))
335
336 (pass-if "program address"
d1100525 337 (and=> (find-program-debug-info (program-code return-3))
cb86cbd7
AW
338 (lambda (pdi)
339 (equal? (program-debug-info-addr pdi)
d1100525 340 (program-code return-3)))))))
e65f80af
AW
341
342(with-test-prefix "procedure name"
343 (pass-if-equal 'foo
344 (procedure-name
345 (assemble-program
2a4daafd 346 '((begin-program foo ((name . foo)))
7396d216
AW
347 (begin-standard-arity () 2 #f)
348 (load-constant 1 42)
349 (return 1)
3185c907 350 (end-arity)
e65f80af 351 (end-program))))))
eb2bc00f 352
4cbe4d72 353(with-test-prefix "simple procedure arity"
eb2bc00f
AW
354 (pass-if-equal "#<procedure foo ()>"
355 (object->string
356 (assemble-program
357 '((begin-program foo ((name . foo)))
7396d216
AW
358 (begin-standard-arity () 2 #f)
359 (load-constant 1 42)
360 (return 1)
eb2bc00f
AW
361 (end-arity)
362 (end-program)))))
363 (pass-if-equal "#<procedure foo (x y)>"
364 (object->string
365 (assemble-program
366 '((begin-program foo ((name . foo)))
7396d216 367 (begin-standard-arity (x y) 3 #f)
4cbe4d72
AW
368 (definition x 1)
369 (definition y 2)
7396d216
AW
370 (load-constant 1 42)
371 (return 1)
eb2bc00f
AW
372 (end-arity)
373 (end-program)))))
374
375 (pass-if-equal "#<procedure foo (x #:optional y . z)>"
376 (object->string
377 (assemble-program
378 '((begin-program foo ((name . foo)))
7396d216 379 (begin-opt-arity (x) (y) z 4 #f)
4cbe4d72
AW
380 (definition x 1)
381 (definition y 2)
382 (definition z 3)
7396d216
AW
383 (load-constant 1 42)
384 (return 1)
eb2bc00f
AW
385 (end-arity)
386 (end-program))))))
bf8328ec
AW
387
388(with-test-prefix "procedure docstrings"
389 (pass-if-equal "qux qux"
390 (procedure-documentation
391 (assemble-program
392 '((begin-program foo ((name . foo) (documentation . "qux qux")))
7396d216
AW
393 (begin-standard-arity () 2 #f)
394 (load-constant 1 42)
395 (return 1)
bf8328ec
AW
396 (end-arity)
397 (end-program))))))
c4c098e3
AW
398
399(with-test-prefix "procedure properties"
400 ;; No properties.
401 (pass-if-equal '()
402 (procedure-properties
403 (assemble-program
404 '((begin-program foo ())
7396d216
AW
405 (begin-standard-arity () 2 #f)
406 (load-constant 1 42)
407 (return 1)
c4c098e3
AW
408 (end-arity)
409 (end-program)))))
410
411 ;; Name and docstring (which actually don't go out to procprops).
412 (pass-if-equal '((name . foo)
413 (documentation . "qux qux"))
414 (procedure-properties
415 (assemble-program
416 '((begin-program foo ((name . foo) (documentation . "qux qux")))
7396d216
AW
417 (begin-standard-arity () 2 #f)
418 (load-constant 1 42)
419 (return 1)
c4c098e3
AW
420 (end-arity)
421 (end-program)))))
422
423 ;; A property that actually needs serialization.
424 (pass-if-equal '((name . foo)
425 (documentation . "qux qux")
426 (moo . "mooooooooooooo"))
427 (procedure-properties
428 (assemble-program
429 '((begin-program foo ((name . foo)
430 (documentation . "qux qux")
431 (moo . "mooooooooooooo")))
7396d216
AW
432 (begin-standard-arity () 2 #f)
433 (load-constant 1 42)
434 (return 1)
c4c098e3
AW
435 (end-arity)
436 (end-program)))))
437
438 ;; Procedure-name still works in this case.
439 (pass-if-equal 'foo
440 (procedure-name
441 (assemble-program
442 '((begin-program foo ((name . foo)
443 (documentation . "qux qux")
444 (moo . "mooooooooooooo")))
7396d216
AW
445 (begin-standard-arity () 2 #f)
446 (load-constant 1 42)
447 (return 1)
c4c098e3
AW
448 (end-arity)
449 (end-program))))))