1 ! Copyright (C) 2004, 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: byte-arrays arrays assocs kernel kernel.private libc math
4 namespaces make parser sequences strings words splitting math.parser
5 cpu.architecture alien alien.accessors alien.strings quotations
6 layouts system compiler.units io io.files io.encodings.binary
7 io.streams.memory accessors combinators effects continuations fry
8 classes vocabs vocabs.loader ;
14 : little-endian? ( -- ? ) 1 <int> *char 1 = ; foldable
16 TUPLE: abstract-c-type
17 { class class initial: object }
18 { boxed-class class initial: object }
19 { boxer-quot callable }
20 { unboxer-quot callable }
28 direct-array-constructor ;
30 TUPLE: c-type < abstract-c-type
33 { rep initial: int-rep }
36 : <c-type> ( -- type )
42 c-types [ H{ } assoc-like ] change
45 ERROR: no-c-type name ;
47 : (c-type) ( name -- type/f )
48 c-types get-global at dup [
49 dup string? [ (c-type) ] when
53 GENERIC: c-type ( name -- type ) foldable
55 : resolve-pointer-type ( name -- name )
56 c-types get at dup string?
57 [ "*" append ] [ drop "void*" ] if
60 : resolve-typedef ( name -- type )
61 dup string? [ c-type ] when ;
63 : parse-array-type ( name -- array )
65 [ [ "]" ?tail drop string>number ] map ] dip prefix ;
67 M: string c-type ( name -- type )
68 CHAR: ] over member? [
74 "*" ?tail [ resolve-pointer-type ] [ no-c-type ] if
78 : ?require-word ( word/pair -- )
79 dup word? [ drop ] [ first require ] ?if ;
81 ! These words being foldable means that words need to be
82 ! recompiled if a C type is redefined. Even so, folding the
83 ! size facilitates some optimizations.
84 GENERIC: heap-size ( type -- size ) foldable
86 M: string heap-size c-type heap-size ;
88 M: abstract-c-type heap-size size>> ;
90 GENERIC: require-c-array ( c-type -- )
92 M: object require-c-array
95 M: c-type require-c-array
96 array-class>> ?require-word ;
98 M: string require-c-array
99 c-type require-c-array ;
101 M: array require-c-array
102 first c-type require-c-array ;
104 ERROR: specialized-array-vocab-not-loaded vocab word ;
106 : c-array-constructor ( c-type -- word )
107 array-constructor>> dup array?
108 [ first2 specialized-array-vocab-not-loaded ] when ; foldable
110 : c-(array)-constructor ( c-type -- word )
111 (array)-constructor>> dup array?
112 [ first2 specialized-array-vocab-not-loaded ] when ; foldable
114 : c-direct-array-constructor ( c-type -- word )
115 direct-array-constructor>> dup array?
116 [ first2 specialized-array-vocab-not-loaded ] when ; foldable
118 GENERIC: <c-array> ( len c-type -- array )
120 c-array-constructor execute( len -- array ) ; inline
122 c-type <c-array> ; inline
124 first c-type <c-array> ; inline
126 GENERIC: (c-array) ( len c-type -- array )
128 c-(array)-constructor execute( len -- array ) ; inline
130 c-type (c-array) ; inline
132 first c-type (c-array) ; inline
134 GENERIC: <c-direct-array> ( alien len c-type -- array )
135 M: object <c-direct-array>
136 c-direct-array-constructor execute( alien len -- array ) ; inline
137 M: string <c-direct-array>
138 c-type <c-direct-array> ; inline
139 M: array <c-direct-array>
140 first c-type <c-direct-array> ; inline
142 : malloc-array ( n type -- alien )
143 [ heap-size calloc ] [ <c-direct-array> ] 2bi ; inline
145 : (malloc-array) ( n type -- alien )
146 [ heap-size * malloc ] [ <c-direct-array> ] 2bi ; inline
148 GENERIC: c-type-class ( name -- class )
150 M: abstract-c-type c-type-class class>> ;
152 M: string c-type-class c-type c-type-class ;
154 GENERIC: c-type-boxed-class ( name -- class )
156 M: abstract-c-type c-type-boxed-class boxed-class>> ;
158 M: string c-type-boxed-class c-type c-type-boxed-class ;
160 GENERIC: c-type-boxer ( name -- boxer )
162 M: c-type c-type-boxer boxer>> ;
164 M: string c-type-boxer c-type c-type-boxer ;
166 GENERIC: c-type-boxer-quot ( name -- quot )
168 M: abstract-c-type c-type-boxer-quot boxer-quot>> ;
170 M: string c-type-boxer-quot c-type c-type-boxer-quot ;
172 GENERIC: c-type-unboxer ( name -- boxer )
174 M: c-type c-type-unboxer unboxer>> ;
176 M: string c-type-unboxer c-type c-type-unboxer ;
178 GENERIC: c-type-unboxer-quot ( name -- quot )
180 M: abstract-c-type c-type-unboxer-quot unboxer-quot>> ;
182 M: string c-type-unboxer-quot c-type c-type-unboxer-quot ;
184 GENERIC: c-type-rep ( name -- rep )
186 M: c-type c-type-rep rep>> ;
188 M: string c-type-rep c-type c-type-rep ;
190 GENERIC: c-type-getter ( name -- quot )
192 M: c-type c-type-getter getter>> ;
194 M: string c-type-getter c-type c-type-getter ;
196 GENERIC: c-type-setter ( name -- quot )
198 M: c-type c-type-setter setter>> ;
200 M: string c-type-setter c-type c-type-setter ;
202 GENERIC: c-type-align ( name -- n )
204 M: abstract-c-type c-type-align align>> ;
206 M: string c-type-align c-type c-type-align ;
208 GENERIC: c-type-stack-align? ( name -- ? )
210 M: c-type c-type-stack-align? stack-align?>> ;
212 M: string c-type-stack-align? c-type c-type-stack-align? ;
214 : c-type-box ( n type -- )
215 [ c-type-rep ] [ c-type-boxer [ "No boxer" throw ] unless* ] bi
218 : c-type-unbox ( n ctype -- )
219 [ c-type-rep ] [ c-type-unboxer [ "No unboxer" throw ] unless* ] bi
222 GENERIC: box-parameter ( n ctype -- )
224 M: c-type box-parameter c-type-box ;
226 M: string box-parameter c-type box-parameter ;
228 GENERIC: box-return ( ctype -- )
230 M: c-type box-return f swap c-type-box ;
232 M: string box-return c-type box-return ;
234 GENERIC: unbox-parameter ( n ctype -- )
236 M: c-type unbox-parameter c-type-unbox ;
238 M: string unbox-parameter c-type unbox-parameter ;
240 GENERIC: unbox-return ( ctype -- )
242 M: c-type unbox-return f swap c-type-unbox ;
244 M: string unbox-return c-type unbox-return ;
246 GENERIC: stack-size ( type -- size ) foldable
248 M: string stack-size c-type stack-size ;
250 M: c-type stack-size size>> cell align ;
252 GENERIC: byte-length ( seq -- n ) flushable
254 M: byte-array byte-length length ; inline
256 M: f byte-length drop 0 ; inline
258 : c-getter ( name -- quot )
260 [ "Cannot read struct fields with this type" throw ]
263 : c-type-getter-boxer ( name -- quot )
264 [ c-getter ] [ c-type-boxer-quot ] bi append ;
266 : c-setter ( name -- quot )
268 [ "Cannot write struct fields with this type" throw ]
271 : <c-object> ( type -- array )
272 heap-size <byte-array> ; inline
274 : (c-object) ( type -- array )
275 heap-size (byte-array) ; inline
277 : malloc-object ( type -- alien )
278 1 swap heap-size calloc ; inline
280 : (malloc-object) ( type -- alien )
281 heap-size malloc ; inline
283 : malloc-byte-array ( byte-array -- alien )
284 dup byte-length [ nip malloc dup ] 2keep memcpy ;
286 : memory>byte-array ( alien len -- byte-array )
287 [ nip (byte-array) dup ] 2keep memcpy ;
289 : malloc-string ( string encoding -- alien )
290 string>alien malloc-byte-array ;
292 M: memory-stream stream-read
294 [ index>> ] [ alien>> ] bi <displaced-alien>
295 swap memory>byte-array
296 ] [ [ + ] change-index drop ] 2bi ;
298 : byte-array>memory ( byte-array base -- )
299 swap dup byte-length memcpy ; inline
301 : array-accessor ( type quot -- def )
303 \ swap , [ heap-size , [ * >fixnum ] % ] [ % ] bi*
306 : typedef ( old new -- ) c-types get set-at ;
308 TUPLE: long-long-type < c-type ;
310 : <long-long-type> ( -- type )
313 M: long-long-type unbox-parameter ( n type -- )
314 c-type-unboxer %unbox-long-long ;
316 M: long-long-type unbox-return ( type -- )
317 f swap unbox-parameter ;
319 M: long-long-type box-parameter ( n type -- )
320 c-type-boxer %box-long-long ;
322 M: long-long-type box-return ( type -- )
323 f swap box-parameter ;
325 : define-deref ( name -- )
326 [ CHAR: * prefix "alien.c-types" create ] [ c-getter 0 prefix ] bi
327 (( c-ptr -- value )) define-inline ;
329 : define-out ( name -- )
330 [ "alien.c-types" constructor-word ]
331 [ dup c-setter '[ _ <c-object> [ 0 @ ] keep ] ] bi
332 (( value -- c-ptr )) define-inline ;
334 : >c-bool ( ? -- int ) 1 0 ? ; inline
336 : c-bool> ( int -- ? ) 0 = not ; inline
338 : define-primitive-type ( type name -- )
344 : malloc-file-contents ( path -- alien len )
345 binary file-contents [ malloc-byte-array ] [ length ] bi ;
347 : if-void ( type true false -- )
348 pick "void" = [ drop nip call ] [ nip call ] if ; inline
350 : ?lookup ( vocab word -- word/pair )
351 over vocab [ swap lookup ] [ 2array ] if ;
353 : set-array-class* ( c-type vocab-stem type-stem -- c-type )
356 [ "specialized-arrays." prepend ]
357 [ "-array" append ] bi* ?lookup >>array-class
360 [ "specialized-arrays." prepend ]
361 [ "<" "-array>" surround ] bi* ?lookup >>array-constructor
364 [ "specialized-arrays." prepend ]
365 [ "(" "-array)" surround ] bi* ?lookup >>(array)-constructor
368 [ "specialized-arrays." prepend ]
369 [ "<direct-" "-array>" surround ] bi* ?lookup >>direct-array-constructor
373 : set-array-class ( c-type stem -- c-type )
374 dup set-array-class* ;
376 CONSTANT: primitive-types
382 "longlong" "ulonglong"
391 [ alien-cell ] >>getter
392 [ [ >c-ptr ] 2dip set-alien-cell ] >>setter
393 bootstrap-cell >>size
394 bootstrap-cell >>align
395 [ >c-ptr ] >>unboxer-quot
397 "alien_offset" >>unboxer
398 "alien" "void*" set-array-class*
399 "void*" define-primitive-type
403 integer >>boxed-class
404 [ alien-signed-8 ] >>getter
405 [ set-alien-signed-8 ] >>setter
408 "box_signed_8" >>boxer
409 "to_signed_8" >>unboxer
410 "longlong" set-array-class
411 "longlong" define-primitive-type
415 integer >>boxed-class
416 [ alien-unsigned-8 ] >>getter
417 [ set-alien-unsigned-8 ] >>setter
420 "box_unsigned_8" >>boxer
421 "to_unsigned_8" >>unboxer
422 "ulonglong" set-array-class
423 "ulonglong" define-primitive-type
427 integer >>boxed-class
428 [ alien-signed-cell ] >>getter
429 [ set-alien-signed-cell ] >>setter
430 bootstrap-cell >>size
431 bootstrap-cell >>align
432 "box_signed_cell" >>boxer
433 "to_fixnum" >>unboxer
434 "long" set-array-class
435 "long" define-primitive-type
439 integer >>boxed-class
440 [ alien-unsigned-cell ] >>getter
441 [ set-alien-unsigned-cell ] >>setter
442 bootstrap-cell >>size
443 bootstrap-cell >>align
444 "box_unsigned_cell" >>boxer
446 "ulong" set-array-class
447 "ulong" define-primitive-type
451 integer >>boxed-class
452 [ alien-signed-4 ] >>getter
453 [ set-alien-signed-4 ] >>setter
456 "box_signed_4" >>boxer
457 "to_fixnum" >>unboxer
458 "int" set-array-class
459 "int" define-primitive-type
463 integer >>boxed-class
464 [ alien-unsigned-4 ] >>getter
465 [ set-alien-unsigned-4 ] >>setter
468 "box_unsigned_4" >>boxer
470 "uint" set-array-class
471 "uint" define-primitive-type
476 [ alien-signed-2 ] >>getter
477 [ set-alien-signed-2 ] >>setter
480 "box_signed_2" >>boxer
481 "to_fixnum" >>unboxer
482 "short" set-array-class
483 "short" define-primitive-type
488 [ alien-unsigned-2 ] >>getter
489 [ set-alien-unsigned-2 ] >>setter
492 "box_unsigned_2" >>boxer
494 "ushort" set-array-class
495 "ushort" define-primitive-type
500 [ alien-signed-1 ] >>getter
501 [ set-alien-signed-1 ] >>setter
504 "box_signed_1" >>boxer
505 "to_fixnum" >>unboxer
506 "char" set-array-class
507 "char" define-primitive-type
512 [ alien-unsigned-1 ] >>getter
513 [ set-alien-unsigned-1 ] >>setter
516 "box_unsigned_1" >>boxer
518 "uchar" set-array-class
519 "uchar" define-primitive-type
522 [ alien-unsigned-1 c-bool> ] >>getter
523 [ [ >c-bool ] 2dip set-alien-unsigned-1 ] >>setter
526 "box_boolean" >>boxer
527 "to_boolean" >>unboxer
528 "bool" set-array-class
529 "bool" define-primitive-type
534 [ alien-float ] >>getter
535 [ [ >float ] 2dip set-alien-float ] >>setter
541 [ >float ] >>unboxer-quot
542 "float" set-array-class
543 "float" define-primitive-type
548 [ alien-double ] >>getter
549 [ [ >float ] 2dip set-alien-double ] >>setter
553 "to_double" >>unboxer
555 [ >float ] >>unboxer-quot
556 "double" set-array-class
557 "double" define-primitive-type
559 "long" "ptrdiff_t" typedef
560 "long" "intptr_t" typedef
561 "ulong" "size_t" typedef
562 ] with-compilation-unit