]> gitweb.factorcode.org Git - factor.git/blob - basis/compiler/tests/alien.factor
1428ba1b662a94ff2535f0e821053b85a46b39ee
[factor.git] / basis / compiler / tests / alien.factor
1 USING: accessors alien alien.c-types alien.libraries
2 alien.syntax arrays classes.struct combinators
3 compiler continuations effects io io.backend io.pathnames
4 io.streams.string kernel math memory namespaces
5 namespaces.private parser quotations sequences
6 specialized-arrays.float stack-checker stack-checker.errors
7 system threads tools.test words specialized-arrays.char ;
8 IN: compiler.tests.alien
9
10 <<
11 : libfactor-ffi-tests-path ( -- string )
12     "resource:" (normalize-path)
13     {
14         { [ os winnt? ]  [ "libfactor-ffi-test.dll" ] }
15         { [ os macosx? ] [ "libfactor-ffi-test.dylib" ] }
16         { [ os unix?  ]  [ "libfactor-ffi-test.so" ] }
17     } cond append-path ;
18
19 "f-cdecl" libfactor-ffi-tests-path "cdecl" add-library
20
21 "f-stdcall" libfactor-ffi-tests-path "stdcall" add-library
22 >>
23
24 LIBRARY: f-cdecl
25
26 FUNCTION: void ffi_test_0 ;
27 [ ] [ ffi_test_0 ] unit-test
28
29 FUNCTION: int ffi_test_1 ;
30 [ 3 ] [ ffi_test_1 ] unit-test
31
32 FUNCTION: int ffi_test_2 int x int y ;
33 [ 5 ] [ 2 3 ffi_test_2 ] unit-test
34 [ "hi" 3 ffi_test_2 ] must-fail
35
36 FUNCTION: int ffi_test_3 int x int y int z int t ;
37 [ 25 ] [ 2 3 4 5 ffi_test_3 ] unit-test
38
39 FUNCTION: float ffi_test_4 ;
40 [ 1.5 ] [ ffi_test_4 ] unit-test
41
42 FUNCTION: double ffi_test_5 ;
43 [ 1.5 ] [ ffi_test_5 ] unit-test
44
45 FUNCTION: int ffi_test_9 int a int b int c int d int e int f int g ;
46 [ 28 ] [ 1 2 3 4 5 6 7 ffi_test_9 ] unit-test
47 [ "a" 2 3 4 5 6 7 ffi_test_9 ] must-fail
48 [ 1 2 3 4 5 6 "a" ffi_test_9 ] must-fail
49
50 STRUCT: FOO { x int } { y int } ;
51
52 : make-FOO ( x y -- FOO )
53     FOO <struct> swap >>y swap >>x ;
54
55 FUNCTION: int ffi_test_11 int a FOO b int c ;
56
57 [ 14 ] [ 1 2 3 make-FOO 4 ffi_test_11 ] unit-test
58
59 FUNCTION: int ffi_test_13 int a int b int c int d int e int f int g int h int i int j int k ;
60
61 [ 66 ] [ 1 2 3 4 5 6 7 8 9 10 11 ffi_test_13 ] unit-test
62
63 FUNCTION: FOO ffi_test_14 int x int y ;
64
65 [ 11 6 ] [ 11 6 ffi_test_14 [ x>> ] [ y>> ] bi ] unit-test
66
67 FUNCTION: char* ffi_test_15 char* x char* y ;
68
69 [ "foo" ] [ "xy" "zt" ffi_test_15 ] unit-test
70 [ "bar" ] [ "xy" "xy" ffi_test_15 ] unit-test
71 [ 1 2 ffi_test_15 ] must-fail
72
73 STRUCT: BAR { x long } { y long } { z long } ;
74
75 FUNCTION: BAR ffi_test_16 long x long y long z ;
76
77 [ 11 6 -7 ] [
78     11 6 -7 ffi_test_16 [ x>> ] [ y>> ] [ z>> ] tri
79 ] unit-test
80
81 STRUCT: TINY { x int } ;
82
83 FUNCTION: TINY ffi_test_17 int x ;
84
85 [ 11 ] [ 11 ffi_test_17 x>> ] unit-test
86
87 [ [ alien-indirect ] infer ] [ inference-error? ] must-fail-with
88
89 : indirect-test-1 ( ptr -- result )
90     "int" { } "cdecl" alien-indirect ;
91
92 { 1 1 } [ indirect-test-1 ] must-infer-as
93
94 [ 3 ] [ &: ffi_test_1 indirect-test-1 ] unit-test
95
96 : indirect-test-1' ( ptr -- )
97     "int" { } "cdecl" alien-indirect drop ;
98
99 { 1 0 } [ indirect-test-1' ] must-infer-as
100
101 [ ] [ &: ffi_test_1 indirect-test-1' ] unit-test
102
103 [ -1 indirect-test-1 ] must-fail
104
105 : indirect-test-2 ( x y ptr -- result )
106     "int" { "int" "int" } "cdecl" alien-indirect gc ;
107
108 { 3 1 } [ indirect-test-2 ] must-infer-as
109
110 [ 5 ]
111 [ 2 3 &: ffi_test_2 indirect-test-2 ]
112 unit-test
113
114 : indirect-test-3 ( a b c d ptr -- result )
115     "int" { "int" "int" "int" "int" } "stdcall" alien-indirect
116     gc ;
117
118 [ f ] [ "f-stdcall" load-library f = ] unit-test
119 [ "stdcall" ] [ "f-stdcall" library abi>> ] unit-test
120
121 : ffi_test_18 ( w x y z -- int )
122     "int" "f-stdcall" "ffi_test_18" { "int" "int" "int" "int" }
123     alien-invoke gc ;
124
125 [ 25 ] [ 2 3 4 5 ffi_test_18 ] unit-test
126
127 : ffi_test_19 ( x y z -- BAR )
128     "BAR" "f-stdcall" "ffi_test_19" { "long" "long" "long" }
129     alien-invoke gc ;
130
131 [ 11 6 -7 ] [
132     11 6 -7 ffi_test_19 [ x>> ] [ y>> ] [ z>> ] tri
133 ] unit-test
134
135 FUNCTION: double ffi_test_6 float x float y ;
136 [ 6.0 ] [ 3.0 2.0 ffi_test_6 ] unit-test
137 [ "a" "b" ffi_test_6 ] must-fail
138
139 FUNCTION: double ffi_test_7 double x double y ;
140 [ 6.0 ] [ 3.0 2.0 ffi_test_7 ] unit-test
141
142 FUNCTION: double ffi_test_8 double x float y double z float t int w ;
143 [ 19.0 ] [ 3.0 2.0 1.0 6.0 7 ffi_test_8 ] unit-test
144
145 FUNCTION: int ffi_test_10 int a int b double c int d float e int f int g int h ;
146 [ -34 ] [ 1 2 3.0 4 5.0 6 7 8 ffi_test_10 ] unit-test
147
148 FUNCTION: void ffi_test_20 double x1, double x2, double x3,
149     double y1, double y2, double y3,
150     double z1, double z2, double z3 ;
151
152 [ ] [ 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 ffi_test_20 ] unit-test
153
154 ! Make sure XT doesn't get clobbered in stack frame
155
156 : ffi_test_31 ( a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a -- result y )
157     "int"
158     "f-cdecl" "ffi_test_31"
159     { "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" }
160     alien-invoke gc 3 ;
161
162 [ 861 3 ] [ 42 [ ] each ffi_test_31 ] unit-test
163
164 : ffi_test_31_point_5 ( a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a -- result )
165     "float"
166     "f-cdecl" "ffi_test_31_point_5"
167     { "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" "float" }
168     alien-invoke ;
169
170 [ 861.0 ] [ 42 [ >float ] each ffi_test_31_point_5 ] unit-test
171
172 FUNCTION: longlong ffi_test_21 long x long y ;
173
174 [ 121932631112635269 ]
175 [ 123456789 987654321 ffi_test_21 ] unit-test
176
177 FUNCTION: long ffi_test_22 long x longlong y longlong z ;
178
179 [ 987655432 ]
180 [ 1111 121932631112635269 123456789 ffi_test_22 ] unit-test
181
182 [ 1111 f 123456789 ffi_test_22 ] must-fail
183
184 STRUCT: RECT
185     { x float } { y float }
186     { w float } { h float } ;
187
188 : <RECT> ( x y w h -- rect )
189     RECT <struct>
190         swap >>h
191         swap >>w
192         swap >>y
193         swap >>x ;
194
195 FUNCTION: int ffi_test_12 int a int b RECT c int d int e int f ;
196
197 [ 45 ] [ 1 2 3.0 4.0 5.0 6.0 <RECT> 7 8 9 ffi_test_12 ] unit-test
198
199 [ 1 2 { 1 2 3 } 7 8 9 ffi_test_12 ] must-fail
200
201 FUNCTION: float ffi_test_23 ( float[3] x, float[3] y ) ;
202
203 [ 32.0 ] [
204     { 1.0 2.0 3.0 } >float-array
205     { 4.0 5.0 6.0 } >float-array
206     ffi_test_23
207 ] unit-test
208
209 ! Test odd-size structs
210 STRUCT: test-struct-1 { x char[1] } ;
211
212 FUNCTION: test-struct-1 ffi_test_24 ;
213
214 [ S{ test-struct-1 { x char-array{ 1 } } } ] [ ffi_test_24 ] unit-test
215
216 STRUCT: test-struct-2 { x char[2] } ;
217
218 FUNCTION: test-struct-2 ffi_test_25 ;
219
220 [ S{ test-struct-2 { x char-array{ 1 2 } } } ] [ ffi_test_25 ] unit-test
221
222 STRUCT: test-struct-3 { x char[3] } ;
223
224 FUNCTION: test-struct-3 ffi_test_26 ;
225
226 [ S{ test-struct-3 { x char-array{ 1 2 3 } } } ] [ ffi_test_26 ] unit-test
227
228 STRUCT: test-struct-4 { x char[4] } ;
229
230 FUNCTION: test-struct-4 ffi_test_27 ;
231
232 [ S{ test-struct-4 { x char-array{ 1 2 3 4 } } } ] [ ffi_test_27 ] unit-test
233
234 STRUCT: test-struct-5 { x char[5] } ;
235
236 FUNCTION: test-struct-5 ffi_test_28 ;
237
238 [ S{ test-struct-5 { x char-array{ 1 2 3 4 5 } } } ] [ ffi_test_28 ] unit-test
239
240 STRUCT: test-struct-6 { x char[6] } ;
241
242 FUNCTION: test-struct-6 ffi_test_29 ;
243
244 [ S{ test-struct-6 { x char-array{ 1 2 3 4 5 6 } } } ] [ ffi_test_29 ] unit-test
245
246 STRUCT: test-struct-7 { x char[7] } ;
247
248 FUNCTION: test-struct-7 ffi_test_30 ;
249
250 [ S{ test-struct-7 { x char-array{ 1 2 3 4 5 6 7 } } } ] [ ffi_test_30 ] unit-test
251
252 STRUCT: test-struct-8 { x double } { y double } ;
253
254 FUNCTION: double ffi_test_32 test-struct-8 x int y ;
255
256 [ 9.0 ] [
257     test-struct-8 <struct>
258     1.0 >>x
259     2.0 >>y
260     3 ffi_test_32
261 ] unit-test
262
263 STRUCT: test-struct-9 { x float } { y float } ;
264
265 FUNCTION: double ffi_test_33 test-struct-9 x int y ;
266
267 [ 9.0 ] [
268     test-struct-9 <struct>
269     1.0 >>x
270     2.0 >>y
271     3 ffi_test_33
272 ] unit-test
273
274 STRUCT: test-struct-10 { x float } { y int } ;
275
276 FUNCTION: double ffi_test_34 test-struct-10 x int y ;
277
278 [ 9.0 ] [
279     test-struct-10 <struct>
280     1.0 >>x
281     2 >>y
282     3 ffi_test_34
283 ] unit-test
284
285 STRUCT: test-struct-11 { x int } { y int } ;
286
287 FUNCTION: double ffi_test_35 test-struct-11 x int y ;
288
289 [ 9.0 ] [
290     test-struct-11 <struct>
291     1 >>x
292     2 >>y
293     3 ffi_test_35
294 ] unit-test
295
296 STRUCT: test-struct-12 { a int } { x double } ;
297
298 : make-struct-12 ( x -- alien )
299     test-struct-12 <struct>
300         swap >>x ;
301
302 FUNCTION: double ffi_test_36 ( test-struct-12 x ) ;
303
304 [ 1.23456 ] [ 1.23456 make-struct-12 ffi_test_36 ] unit-test
305
306 FUNCTION: ulonglong ffi_test_38 ( ulonglong x, ulonglong y ) ;
307
308 [ t ] [ 31 2^ 32 2^ ffi_test_38 63 2^ = ] unit-test
309
310 ! Test callbacks
311
312 : callback-1 ( -- callback ) "void" { } "cdecl" [ ] alien-callback ;
313
314 [ 0 1 ] [ [ callback-1 ] infer [ in>> ] [ out>> ] bi ] unit-test
315
316 [ t ] [ callback-1 alien? ] unit-test
317
318 : callback_test_1 ( ptr -- ) "void" { } "cdecl" alien-indirect ;
319
320 [ ] [ callback-1 callback_test_1 ] unit-test
321
322 : callback-2 ( -- callback ) "void" { } "cdecl" [ [ 5 throw ] ignore-errors ] alien-callback ;
323
324 [ ] [ callback-2 callback_test_1 ] unit-test
325
326 : callback-3 ( -- callback ) "void" { } "cdecl" [ 5 "x" set ] alien-callback ;
327
328 [ t ] [
329     namestack*
330     3 "x" set callback-3 callback_test_1
331     namestack* eq?
332 ] unit-test
333
334 [ 5 ] [
335     [
336         3 "x" set callback-3 callback_test_1 "x" get
337     ] with-scope
338 ] unit-test
339
340 : callback-4 ( -- callback )
341     "void" { } "cdecl" [ "Hello world" write ] alien-callback
342     gc ;
343
344 [ "Hello world" ] [
345     [ callback-4 callback_test_1 ] with-string-writer
346 ] unit-test
347
348 : callback-5 ( -- callback )
349     "void" { } "cdecl" [ gc ] alien-callback ;
350
351 [ "testing" ] [
352     "testing" callback-5 callback_test_1
353 ] unit-test
354
355 : callback-5a ( -- callback )
356     "void" { } "cdecl" [ 8000000 f <array> drop ] alien-callback ;
357
358 ! Hack; if we're on ARM, we probably don't have much RAM, so
359 ! skip this test.
360 ! cpu "arm" = [
361 !     [ "testing" ] [
362 !         "testing" callback-5a callback_test_1
363 !     ] unit-test
364 ! ] unless
365
366 : callback-6 ( -- callback )
367     "void" { } "cdecl" [ [ continue ] callcc0 ] alien-callback ;
368
369 [ 1 2 3 ] [ callback-6 callback_test_1 1 2 3 ] unit-test
370
371 : callback-7 ( -- callback )
372     "void" { } "cdecl" [ 1000000 sleep ] alien-callback ;
373
374 [ 1 2 3 ] [ callback-7 callback_test_1 1 2 3 ] unit-test
375
376 [ f ] [ namespace global eq? ] unit-test
377
378 : callback-8 ( -- callback )
379     "void" { } "cdecl" [
380         [ continue ] callcc0
381     ] alien-callback ;
382
383 [ ] [ callback-8 callback_test_1 ] unit-test
384
385 : callback-9 ( -- callback )
386     "int" { "int" "int" "int" } "cdecl" [
387         + + 1 +
388     ] alien-callback ;
389
390 FUNCTION: void ffi_test_36_point_5 ( ) ;
391
392 [ ] [ ffi_test_36_point_5 ] unit-test
393
394 FUNCTION: int ffi_test_37 ( void* func ) ;
395
396 [ 1 ] [ callback-9 ffi_test_37 ] unit-test
397
398 [ 7 ] [ callback-9 ffi_test_37 ] unit-test
399
400 STRUCT: test_struct_13
401 { x1 float }
402 { x2 float }
403 { x3 float }
404 { x4 float }
405 { x5 float }
406 { x6 float } ;
407
408 : make-test-struct-13 ( -- alien )
409     test_struct_13 <struct>
410         1.0 >>x1
411         2.0 >>x2
412         3.0 >>x3
413         4.0 >>x4
414         5.0 >>x5
415         6.0 >>x6 ;
416
417 FUNCTION: int ffi_test_39 ( long a, long b, test_struct_13 s ) ;
418
419 [ 21 ] [ 12347 12347 make-test-struct-13 ffi_test_39 ] unit-test
420
421 ! Joe Groff found this problem
422 STRUCT: double-rect
423 { a double }
424 { b double }
425 { c double }
426 { d double } ;
427
428 : <double-rect> ( a b c d -- foo )
429     double-rect <struct>
430         swap >>d
431         swap >>c
432         swap >>b
433         swap >>a ;
434
435 : >double-rect< ( foo -- a b c d )
436     {
437         [ a>> ]
438         [ b>> ]
439         [ c>> ]
440         [ d>> ]
441     } cleave ;
442
443 : double-rect-callback ( -- alien )
444     "void" { "void*" "void*" "double-rect" } "cdecl"
445     [ "example" set-global 2drop ] alien-callback ;
446
447 : double-rect-test ( arg -- arg' )
448     f f rot
449     double-rect-callback
450     "void" { "void*" "void*" "double-rect" } "cdecl" alien-indirect
451     "example" get-global ;
452
453 [ 1.0 2.0 3.0 4.0 ]
454 [ 1.0 2.0 3.0 4.0 <double-rect> double-rect-test >double-rect< ] unit-test
455
456 STRUCT: test_struct_14
457     { x1 double }
458     { x2 double } ;
459
460 FUNCTION: test_struct_14 ffi_test_40 ( double x1, double x2 ) ;
461
462 [ 1.0 2.0 ] [
463     1.0 2.0 ffi_test_40 [ x1>> ] [ x2>> ] bi
464 ] unit-test
465
466 : callback-10 ( -- callback )
467     "test_struct_14" { "double" "double" } "cdecl"
468     [
469         test_struct_14 <struct>
470             swap >>x2
471             swap >>x1
472     ] alien-callback ;
473
474 : callback-10-test ( x1 x2 callback -- result )
475     "test_struct_14" { "double" "double" } "cdecl" alien-indirect ;
476
477 [ 1.0 2.0 ] [
478     1.0 2.0 callback-10 callback-10-test
479     [ x1>> ] [ x2>> ] bi
480 ] unit-test
481
482 FUNCTION: test-struct-12 ffi_test_41 ( int a, double x ) ;
483
484 [ 1 2.0 ] [
485     1 2.0 ffi_test_41
486     [ a>> ] [ x>> ] bi
487 ] unit-test
488
489 : callback-11 ( -- callback )
490     "test-struct-12" { "int" "double" } "cdecl"
491     [
492         test-struct-12 <struct>
493             swap >>x
494             swap >>a
495     ] alien-callback ;
496
497 : callback-11-test ( x1 x2 callback -- result )
498     "test-struct-12" { "int" "double" } "cdecl" alien-indirect ;
499
500 [ 1 2.0 ] [
501     1 2.0 callback-11 callback-11-test
502     [ a>> ] [ x>> ] bi
503 ] unit-test
504
505 STRUCT: test_struct_15
506     { x float }
507     { y float } ;
508
509 FUNCTION: test_struct_15 ffi_test_42 ( float x, float y ) ;
510
511 [ 1.0 2.0 ] [ 1.0 2.0 ffi_test_42 [ x>> ] [ y>> ] bi ] unit-test
512
513 : callback-12 ( -- callback )
514     "test_struct_15" { "float" "float" } "cdecl"
515     [
516         test_struct_15 <struct>
517             swap >>y
518             swap >>x
519     ] alien-callback ;
520
521 : callback-12-test ( x1 x2 callback -- result )
522     "test_struct_15" { "float" "float" } "cdecl" alien-indirect ;
523
524 [ 1.0 2.0 ] [
525     1.0 2.0 callback-12 callback-12-test [ x>> ] [ y>> ] bi
526 ] unit-test
527
528 STRUCT: test_struct_16
529     { x float }
530     { a int } ;
531
532 FUNCTION: test_struct_16 ffi_test_43 ( float x, int a ) ;
533
534 [ 1.0 2 ] [ 1.0 2 ffi_test_43 [ x>> ] [ a>> ] bi ] unit-test
535
536 : callback-13 ( -- callback )
537     "test_struct_16" { "float" "int" } "cdecl"
538     [
539         test_struct_16 <struct>
540             swap >>a
541             swap >>x
542     ] alien-callback ;
543
544 : callback-13-test ( x1 x2 callback -- result )
545     "test_struct_16" { "float" "int" } "cdecl" alien-indirect ;
546
547 [ 1.0 2 ] [
548     1.0 2 callback-13 callback-13-test
549     [ x>> ] [ a>> ] bi
550 ] unit-test
551
552 FUNCTION: test_struct_14 ffi_test_44 ( ) ; inline
553
554 [ 1.0 2.0 ] [ ffi_test_44 [ x1>> ] [ x2>> ] bi ] unit-test
555
556 : stack-frame-bustage ( -- a b ) ffi_test_44 gc 3 ;
557
558 [ ] [ stack-frame-bustage 2drop ] unit-test
559
560 FUNCTION: complex-float ffi_test_45 ( int x ) ;
561
562 [ C{ 3.0 0.0 } ] [ 3 ffi_test_45 ] unit-test
563
564 FUNCTION: complex-double ffi_test_46 ( int x ) ;
565
566 [ C{ 3.0 0.0 } ] [ 3 ffi_test_46 ] unit-test
567
568 FUNCTION: complex-float ffi_test_47 ( complex-float x, complex-double y ) ;
569
570 [ C{ 4.0 4.0 } ] [
571     C{ 1.0 2.0 }
572     C{ 1.5 1.0 } ffi_test_47
573 ] unit-test
574
575 ! Reported by jedahu
576 STRUCT: bool-field-test
577     { name char* }
578     { on bool }
579     { parents short } ;
580
581 FUNCTION: short ffi_test_48 ( bool-field-test x ) ;
582
583 [ 123 ] [
584     bool-field-test <struct>
585         123 >>parents
586     ffi_test_48
587 ] unit-test