]> gitweb.factorcode.org Git - factor.git/blob - basis/alien/c-types/c-types.factor
Merge branch 'master' of git://github.com/littledan/Factor
[factor.git] / basis / alien / c-types / c-types.factor
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 math
4 math.order math.parser namespaces make parser sequences strings
5 words splitting cpu.architecture alien alien.accessors
6 alien.strings quotations layouts system compiler.units io
7 io.files io.encodings.binary io.streams.memory accessors
8 combinators effects continuations fry classes vocabs
9 vocabs.loader words.symbol ;
10 QUALIFIED: math
11 IN: alien.c-types
12
13 SYMBOLS:
14     char uchar
15     short ushort
16     int uint
17     long ulong
18     longlong ulonglong
19     float double
20     void* bool
21     void ;
22
23 DEFER: <int>
24 DEFER: *char
25
26 TUPLE: abstract-c-type
27 { class class initial: object }
28 { boxed-class class initial: object }
29 { boxer-quot callable }
30 { unboxer-quot callable }
31 { getter callable }
32 { setter callable }
33 { size integer }
34 { align integer }
35 { align-first integer } ;
36
37 TUPLE: c-type < abstract-c-type
38 boxer
39 unboxer
40 { rep initial: int-rep }
41 stack-align? ;
42
43 : <c-type> ( -- c-type )
44     \ c-type new ; inline
45
46 SYMBOL: c-types
47
48 global [
49     c-types [ H{ } assoc-like ] change
50 ] bind
51
52 ERROR: no-c-type name ;
53
54 PREDICATE: c-type-word < word
55     "c-type" word-prop ;
56
57 UNION: c-type-name string c-type-word ;
58
59 ! C type protocol
60 GENERIC: c-type ( name -- c-type ) foldable
61
62 GENERIC: resolve-pointer-type ( name -- c-type )
63
64 << \ void \ void* "pointer-c-type" set-word-prop >>
65
66 : void? ( c-type -- ? )
67     { void "void" } member? ;
68
69 M: word resolve-pointer-type
70     dup "pointer-c-type" word-prop
71     [ ] [ drop void* ] ?if ;
72
73 M: string resolve-pointer-type
74     dup "*" append dup c-types get at
75     [ nip ] [
76         drop
77         c-types get at dup c-type-name?
78         [ resolve-pointer-type ] [ drop void* ] if
79     ] if ;
80
81 M: array resolve-pointer-type
82     first resolve-pointer-type ;
83
84 : resolve-typedef ( name -- c-type )
85     dup void? [ no-c-type ] when
86     dup c-type-name? [ c-type ] when ;
87
88 <PRIVATE
89
90 : parse-array-type ( name -- dims c-type )
91     "[" split unclip
92     [ [ "]" ?tail drop string>number ] map ] dip ;
93
94 PRIVATE>
95
96 M: string c-type ( name -- c-type )
97     CHAR: ] over member? [
98         parse-array-type prefix
99     ] [
100         dup c-types get at [ ] [
101             "*" ?tail [ resolve-pointer-type ] [ no-c-type ] if
102         ] ?if resolve-typedef
103     ] if ;
104
105 M: word c-type
106     dup "c-type" word-prop resolve-typedef
107     [ ] [ no-c-type ] ?if ;
108
109 GENERIC: c-struct? ( c-type -- ? )
110
111 M: object c-struct? drop f ;
112
113 M: c-type-name c-struct? dup void? [ drop f ] [ c-type c-struct? ] if ;
114
115 ! These words being foldable means that words need to be
116 ! recompiled if a C type is redefined. Even so, folding the
117 ! size facilitates some optimizations.
118 GENERIC: c-type-class ( name -- class )
119
120 M: abstract-c-type c-type-class class>> ;
121
122 M: c-type-name c-type-class c-type c-type-class ;
123
124 GENERIC: c-type-boxed-class ( name -- class )
125
126 M: abstract-c-type c-type-boxed-class boxed-class>> ;
127
128 M: c-type-name c-type-boxed-class c-type c-type-boxed-class ;
129
130 GENERIC: c-type-boxer ( name -- boxer )
131
132 M: c-type c-type-boxer boxer>> ;
133
134 M: c-type-name c-type-boxer c-type c-type-boxer ;
135
136 GENERIC: c-type-boxer-quot ( name -- quot )
137
138 M: abstract-c-type c-type-boxer-quot boxer-quot>> ;
139
140 M: c-type-name c-type-boxer-quot c-type c-type-boxer-quot ;
141
142 GENERIC: c-type-unboxer ( name -- boxer )
143
144 M: c-type c-type-unboxer unboxer>> ;
145
146 M: c-type-name c-type-unboxer c-type c-type-unboxer ;
147
148 GENERIC: c-type-unboxer-quot ( name -- quot )
149
150 M: abstract-c-type c-type-unboxer-quot unboxer-quot>> ;
151
152 M: c-type-name c-type-unboxer-quot c-type c-type-unboxer-quot ;
153
154 GENERIC: c-type-rep ( name -- rep )
155
156 M: c-type c-type-rep rep>> ;
157
158 M: c-type-name c-type-rep c-type c-type-rep ;
159
160 GENERIC: c-type-getter ( name -- quot )
161
162 M: c-type c-type-getter getter>> ;
163
164 M: c-type-name c-type-getter c-type c-type-getter ;
165
166 GENERIC: c-type-setter ( name -- quot )
167
168 M: c-type c-type-setter setter>> ;
169
170 M: c-type-name c-type-setter c-type c-type-setter ;
171
172 GENERIC: c-type-align ( name -- n )
173
174 M: abstract-c-type c-type-align align>> ;
175
176 M: c-type-name c-type-align c-type c-type-align ;
177
178 GENERIC: c-type-align-first ( name -- n )
179
180 M: c-type-name c-type-align-first c-type c-type-align-first ;
181
182 M: abstract-c-type c-type-align-first align-first>> ;
183
184 GENERIC: c-type-stack-align? ( name -- ? )
185
186 M: c-type c-type-stack-align? stack-align?>> ;
187
188 M: c-type-name c-type-stack-align? c-type c-type-stack-align? ;
189
190 : c-type-box ( n c-type -- )
191     [ c-type-rep ] [ c-type-boxer [ "No boxer" throw ] unless* ] bi
192     %box ;
193
194 : c-type-unbox ( n c-type -- )
195     [ c-type-rep ] [ c-type-unboxer [ "No unboxer" throw ] unless* ] bi
196     %unbox ;
197
198 GENERIC: box-parameter ( n c-type -- )
199
200 M: c-type box-parameter c-type-box ;
201
202 M: c-type-name box-parameter c-type box-parameter ;
203
204 GENERIC: box-return ( c-type -- )
205
206 M: c-type box-return f swap c-type-box ;
207
208 M: c-type-name box-return c-type box-return ;
209
210 GENERIC: unbox-parameter ( n c-type -- )
211
212 M: c-type unbox-parameter c-type-unbox ;
213
214 M: c-type-name unbox-parameter c-type unbox-parameter ;
215
216 GENERIC: unbox-return ( c-type -- )
217
218 M: c-type unbox-return f swap c-type-unbox ;
219
220 M: c-type-name unbox-return c-type unbox-return ;
221
222 : little-endian? ( -- ? ) 1 <int> *char 1 = ; foldable
223
224 GENERIC: heap-size ( name -- size )
225
226 M: c-type-name heap-size c-type heap-size ;
227
228 M: abstract-c-type heap-size size>> ;
229
230 GENERIC: stack-size ( name -- size )
231
232 M: c-type-name stack-size c-type stack-size ;
233
234 M: c-type stack-size size>> cell align ;
235
236 GENERIC: byte-length ( seq -- n ) flushable
237
238 M: byte-array byte-length length ; inline
239
240 M: f byte-length drop 0 ; inline
241
242 : >c-bool ( ? -- int ) 1 0 ? ; inline
243
244 : c-bool> ( int -- ? ) 0 = not ; inline
245
246 MIXIN: value-type
247
248 : c-getter ( name -- quot )
249     c-type-getter [
250         [ "Cannot read struct fields with this type" throw ]
251     ] unless* ;
252
253 : c-type-getter-boxer ( name -- quot )
254     [ c-getter ] [ c-type-boxer-quot ] bi append ;
255
256 : c-setter ( name -- quot )
257     c-type-setter [
258         [ "Cannot write struct fields with this type" throw ]
259     ] unless* ;
260
261 : array-accessor ( c-type quot -- def )
262     [
263         \ swap , [ heap-size , [ * >fixnum ] % ] [ % ] bi*
264     ] [ ] make ;
265
266 GENERIC: typedef ( old new -- )
267
268 PREDICATE: typedef-word < c-type-word
269     "c-type" word-prop c-type-name? ;
270
271 M: string typedef ( old new -- ) c-types get set-at ;
272
273 M: word typedef ( old new -- )
274     {
275         [ nip define-symbol ]
276         [ name>> typedef ]
277         [ swap "c-type" set-word-prop ]
278         [
279             swap dup c-type-name? [
280                 resolve-pointer-type
281                 "pointer-c-type" set-word-prop
282             ] [ 2drop ] if
283         ]
284     } 2cleave ;
285
286 TUPLE: long-long-type < c-type ;
287
288 : <long-long-type> ( -- c-type )
289     long-long-type new ;
290
291 M: long-long-type unbox-parameter ( n c-type -- )
292     c-type-unboxer %unbox-long-long ;
293
294 M: long-long-type unbox-return ( c-type -- )
295     f swap unbox-parameter ;
296
297 M: long-long-type box-parameter ( n c-type -- )
298     c-type-boxer %box-long-long ;
299
300 M: long-long-type box-return ( c-type -- )
301     f swap box-parameter ;
302
303 : define-deref ( c-type -- )
304     [ name>> CHAR: * prefix "alien.c-types" create ] [ c-getter 0 prefix ] bi
305     (( c-ptr -- value )) define-inline ;
306
307 : define-out ( c-type -- )
308     [ name>> "alien.c-types" constructor-word ]
309     [ dup c-setter '[ _ heap-size (byte-array) [ 0 @ ] keep ] ] bi
310     (( value -- c-ptr )) define-inline ;
311
312 : define-primitive-type ( c-type name -- )
313     [ typedef ] [ define-deref ] [ define-out ] tri ;
314
315 : if-void ( c-type true false -- )
316     pick void? [ drop nip call ] [ nip call ] if ; inline
317
318 CONSTANT: primitive-types
319     {
320         char uchar
321         short ushort
322         int uint
323         long ulong
324         longlong ulonglong
325         float double
326         void* bool
327     }
328
329 SYMBOLS:
330     ptrdiff_t intptr_t uintptr_t size_t
331     char* uchar* ;
332
333 : 8-byte-alignment ( c-type -- c-type )
334     {
335         { [ cpu ppc? os macosx? and ] [ 4 >>align 8 >>align-first ] }
336         { [ cpu x86.32? os windows? not and ] [ 4 >>align 4 >>align-first ] }
337         [ 8 >>align 8 >>align-first ]
338     } cond ;
339
340 [
341     <c-type>
342         c-ptr >>class
343         c-ptr >>boxed-class
344         [ alien-cell ] >>getter
345         [ [ >c-ptr ] 2dip set-alien-cell ] >>setter
346         bootstrap-cell >>size
347         bootstrap-cell >>align
348         bootstrap-cell >>align-first
349         [ >c-ptr ] >>unboxer-quot
350         "allot_alien" >>boxer
351         "alien_offset" >>unboxer
352     \ void* define-primitive-type
353
354     <c-type>
355         integer >>class
356         integer >>boxed-class
357         [ alien-signed-4 ] >>getter
358         [ set-alien-signed-4 ] >>setter
359         4 >>size
360         4 >>align
361         4 >>align-first
362         "from_signed_4" >>boxer
363         "to_fixnum" >>unboxer
364     \ int define-primitive-type
365
366     <c-type>
367         integer >>class
368         integer >>boxed-class
369         [ alien-unsigned-4 ] >>getter
370         [ set-alien-unsigned-4 ] >>setter
371         4 >>size
372         4 >>align
373         4 >>align-first
374         "from_unsigned_4" >>boxer
375         "to_cell" >>unboxer
376     \ uint define-primitive-type
377
378     <c-type>
379         fixnum >>class
380         fixnum >>boxed-class
381         [ alien-signed-2 ] >>getter
382         [ set-alien-signed-2 ] >>setter
383         2 >>size
384         2 >>align
385         2 >>align-first
386         "from_signed_2" >>boxer
387         "to_fixnum" >>unboxer
388     \ short define-primitive-type
389
390     <c-type>
391         fixnum >>class
392         fixnum >>boxed-class
393         [ alien-unsigned-2 ] >>getter
394         [ set-alien-unsigned-2 ] >>setter
395         2 >>size
396         2 >>align
397         2 >>align-first
398         "from_unsigned_2" >>boxer
399         "to_cell" >>unboxer
400     \ ushort define-primitive-type
401
402     <c-type>
403         fixnum >>class
404         fixnum >>boxed-class
405         [ alien-signed-1 ] >>getter
406         [ set-alien-signed-1 ] >>setter
407         1 >>size
408         1 >>align
409         1 >>align-first
410         "from_signed_1" >>boxer
411         "to_fixnum" >>unboxer
412     \ char define-primitive-type
413
414     <c-type>
415         fixnum >>class
416         fixnum >>boxed-class
417         [ alien-unsigned-1 ] >>getter
418         [ set-alien-unsigned-1 ] >>setter
419         1 >>size
420         1 >>align
421         1 >>align-first
422         "from_unsigned_1" >>boxer
423         "to_cell" >>unboxer
424     \ uchar define-primitive-type
425
426     cpu ppc? [
427         <c-type>
428             [ alien-unsigned-4 c-bool> ] >>getter
429             [ [ >c-bool ] 2dip set-alien-unsigned-4 ] >>setter
430             4 >>size
431             4 >>align
432             4 >>align-first
433             "from_boolean" >>boxer
434             "to_boolean" >>unboxer
435     ] [
436         <c-type>
437             [ alien-unsigned-1 c-bool> ] >>getter
438             [ [ >c-bool ] 2dip set-alien-unsigned-1 ] >>setter
439             1 >>size
440             1 >>align
441             1 >>align-first
442             "from_boolean" >>boxer
443             "to_boolean" >>unboxer
444     ] if
445     \ bool define-primitive-type
446
447     <c-type>
448         math:float >>class
449         math:float >>boxed-class
450         [ alien-float ] >>getter
451         [ [ >float ] 2dip set-alien-float ] >>setter
452         4 >>size
453         4 >>align
454         4 >>align-first
455         "from_float" >>boxer
456         "to_float" >>unboxer
457         float-rep >>rep
458         [ >float ] >>unboxer-quot
459     \ float define-primitive-type
460
461     <c-type>
462         math:float >>class
463         math:float >>boxed-class
464         [ alien-double ] >>getter
465         [ [ >float ] 2dip set-alien-double ] >>setter
466         8 >>size
467         8-byte-alignment
468         "from_double" >>boxer
469         "to_double" >>unboxer
470         double-rep >>rep
471         [ >float ] >>unboxer-quot
472     \ double define-primitive-type
473
474     cell 8 = [
475         <c-type>
476             integer >>class
477             integer >>boxed-class
478             [ alien-signed-cell ] >>getter
479             [ set-alien-signed-cell ] >>setter
480             bootstrap-cell >>size
481             bootstrap-cell >>align
482             bootstrap-cell >>align-first
483             "from_signed_cell" >>boxer
484             "to_fixnum" >>unboxer
485         \ longlong define-primitive-type
486
487         <c-type>
488             integer >>class
489             integer >>boxed-class
490             [ alien-unsigned-cell ] >>getter
491             [ set-alien-unsigned-cell ] >>setter
492             bootstrap-cell >>size
493             bootstrap-cell >>align
494             bootstrap-cell >>align-first
495             "from_unsigned_cell" >>boxer
496             "to_cell" >>unboxer
497         \ ulonglong define-primitive-type
498
499         os windows? [
500             \ int c-type \ long define-primitive-type
501             \ uint c-type \ ulong define-primitive-type
502         ] [
503             \ longlong c-type \ long define-primitive-type
504             \ ulonglong c-type \ ulong define-primitive-type
505         ] if
506
507         \ longlong c-type \ ptrdiff_t typedef
508         \ longlong c-type \ intptr_t typedef
509
510         \ ulonglong c-type \ uintptr_t typedef
511         \ ulonglong c-type \ size_t typedef
512     ] [
513         <long-long-type>
514             integer >>class
515             integer >>boxed-class
516             [ alien-signed-8 ] >>getter
517             [ set-alien-signed-8 ] >>setter
518             8 >>size
519             8-byte-alignment
520             "from_signed_8" >>boxer
521             "to_signed_8" >>unboxer
522         \ longlong define-primitive-type
523
524         <long-long-type>
525             integer >>class
526             integer >>boxed-class
527             [ alien-unsigned-8 ] >>getter
528             [ set-alien-unsigned-8 ] >>setter
529             8 >>size
530             8-byte-alignment
531             "from_unsigned_8" >>boxer
532             "to_unsigned_8" >>unboxer
533         \ ulonglong define-primitive-type
534
535         \ int c-type \ long define-primitive-type
536         \ uint c-type \ ulong define-primitive-type
537
538         \ int c-type \ ptrdiff_t typedef
539         \ int c-type \ intptr_t typedef
540
541         \ uint c-type \ uintptr_t typedef
542         \ uint c-type \ size_t typedef
543     ] if
544 ] with-compilation-unit
545
546 M: char-16-rep rep-component-type drop char ;
547 M: uchar-16-rep rep-component-type drop uchar ;
548 M: short-8-rep rep-component-type drop short ;
549 M: ushort-8-rep rep-component-type drop ushort ;
550 M: int-4-rep rep-component-type drop int ;
551 M: uint-4-rep rep-component-type drop uint ;
552 M: longlong-2-rep rep-component-type drop longlong ;
553 M: ulonglong-2-rep rep-component-type drop ulonglong ;
554 M: float-4-rep rep-component-type drop float ;
555 M: double-2-rep rep-component-type drop double ;
556
557 : rep-length ( rep -- n )
558     16 swap rep-component-type heap-size /i ; foldable
559
560 : (unsigned-interval) ( bytes -- from to ) [ 0 ] dip 8 * 2^ 1 - ; foldable
561 : unsigned-interval ( c-type -- from to ) heap-size (unsigned-interval) ; foldable
562 : (signed-interval) ( bytes -- from to ) 8 * 1 - 2^ [ neg ] [ 1 - ] bi ; foldable
563 : signed-interval ( c-type -- from to ) heap-size (signed-interval) ; foldable
564
565 : c-type-interval ( c-type -- from to )
566     {
567         { [ dup { float double } member-eq? ] [ drop -1/0. 1/0. ] }
568         { [ dup { char short int long longlong } member-eq? ] [ signed-interval ] }
569         { [ dup { uchar ushort uint ulong ulonglong } member-eq? ] [ unsigned-interval ] }
570     } cond ; foldable
571
572 : c-type-clamp ( value c-type -- value' )
573     dup { float double } member-eq?
574     [ drop ] [ c-type-interval clamp ] if ; inline