]> gitweb.factorcode.org Git - factor.git/blob - core/alien/c-types/c-types.factor
Initial import
[factor.git] / core / alien / c-types / c-types.factor
1 ! Copyright (C) 2004, 2007 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: byte-arrays arrays generator.registers assocs
4 kernel kernel.private libc math namespaces parser sequences
5 strings words assocs splitting math.parser cpu.architecture
6 alien quotations system ;
7 IN: alien.c-types
8
9 TUPLE: c-type
10 boxer prep unboxer
11 getter setter
12 reg-class size align stack-align? ;
13
14 : <c-type> ( -- type )
15     T{ int-regs } { set-c-type-reg-class } \ c-type construct ;
16
17 SYMBOL: c-types
18
19 global [
20     c-types [ H{ } assoc-like ] change
21 ] bind
22
23 TUPLE: no-c-type name ;
24
25 : no-c-type ( type -- * ) \ no-c-type construct-boa throw ;
26
27 : (c-type) ( name -- type/f )
28     c-types get-global at dup [
29         dup string? [ (c-type) ] when
30     ] when ;
31
32 GENERIC: c-type ( name -- type )
33
34 : resolve-pointer-type ( name -- name )
35     c-types get at dup string?
36     [ "*" append ] [ drop "void*" ] if
37     c-type ;
38
39 : resolve-typedef ( name -- type )
40     dup string? [ c-type ] when ;
41
42 : parse-array-type ( name -- array )
43     "[" split unclip
44     >r [ "]" ?tail drop string>number ] map r> add* ;
45
46 M: string c-type ( name -- type )
47     CHAR: ] over member? [
48         parse-array-type
49     ] [
50         dup c-types get at [
51             resolve-typedef
52         ] [
53             "*" ?tail [ resolve-pointer-type ] [ no-c-type ] if
54         ] ?if
55     ] if ;
56
57 : c-type-box ( n type -- )
58     dup c-type-reg-class
59     swap c-type-boxer [ "No boxer" throw ] unless*
60     %box ;
61
62 : c-type-unbox ( n ctype -- )
63     dup c-type-reg-class
64     swap c-type-unboxer [ "No unboxer" throw ] unless*
65     %unbox ;
66
67 M: string c-type-align c-type c-type-align ;
68
69 M: string c-type-stack-align? c-type c-type-stack-align? ;
70
71 GENERIC: box-parameter ( n ctype -- )
72
73 M: c-type box-parameter c-type-box ;
74
75 M: string box-parameter c-type box-parameter ;
76
77 GENERIC: box-return ( ctype -- )
78
79 M: c-type box-return f swap c-type-box ;
80
81 M: string box-return c-type box-return ;
82
83 GENERIC: unbox-parameter ( n ctype -- )
84
85 M: c-type unbox-parameter c-type-unbox ;
86
87 M: string unbox-parameter c-type unbox-parameter ;
88
89 GENERIC: unbox-return ( ctype -- )
90
91 M: c-type unbox-return f swap c-type-unbox ;
92
93 M: string unbox-return c-type unbox-return ;
94
95 ! These words being foldable means that words need to be
96 ! recompiled if a C type is redefined. Even so, folding the
97 ! size facilitates some optimizations.
98 GENERIC: heap-size ( type -- size ) foldable
99
100 M: string heap-size c-type heap-size ;
101
102 M: c-type heap-size c-type-size ;
103
104 GENERIC: stack-size ( type -- size ) foldable
105
106 M: string stack-size c-type stack-size ;
107
108 M: c-type stack-size c-type-size ;
109
110 : c-getter ( name -- quot )
111     c-type c-type-getter [
112         [ "Cannot read struct fields with type" throw ]
113     ] unless* ;
114
115 : c-setter ( name -- quot )
116     c-type c-type-setter [
117         [ "Cannot write struct fields with type" throw ]
118     ] unless* ;
119
120 : <c-array> ( n type -- array )
121     heap-size * <byte-array> ; inline
122
123 : <c-object> ( type -- array )
124     1 swap <c-array> ; inline
125
126 : malloc-array ( n type -- alien )
127     heap-size calloc ; inline
128
129 : malloc-object ( type -- alien )
130     1 swap malloc-array ; inline
131
132 : malloc-byte-array ( byte-array -- alien )
133     dup length dup malloc [ -rot memcpy ] keep ;
134
135 : malloc-char-string ( string -- alien )
136     string>char-alien malloc-byte-array ;
137
138 : malloc-u16-string ( string -- alien )
139     string>u16-alien malloc-byte-array ;
140
141 : (define-nth) ( word type quot -- )
142     >r heap-size [ rot * ] swap add* r> append define-inline ;
143
144 : nth-word ( name vocab -- word )
145     >r "-nth" append r> create ;
146
147 : define-nth ( name vocab -- )
148     dupd nth-word swap dup c-getter (define-nth) ;
149
150 : set-nth-word ( name vocab -- word )
151     >r "set-" swap "-nth" 3append r> create ;
152
153 : define-set-nth ( name vocab -- )
154     dupd set-nth-word swap dup c-setter (define-nth) ;
155
156 : typedef ( old new -- ) c-types get set-at ;
157
158 : define-c-type ( type name vocab -- )
159     >r tuck typedef r> [ define-nth ] 2keep define-set-nth ;
160
161 TUPLE: long-long-type ;
162
163 : <long-long-type> ( type -- type )
164     long-long-type construct-delegate ;
165
166 M: long-long-type unbox-parameter ( n type -- )
167     c-type-unboxer %unbox-long-long ;
168
169 M: long-long-type unbox-return ( type -- )
170     f swap unbox-parameter ;
171
172 M: long-long-type box-parameter ( n type -- )
173     c-type-boxer %box-long-long ;
174
175 M: long-long-type box-return ( type -- )
176     f swap box-parameter ;
177
178 : define-deref ( name vocab -- )
179     >r dup CHAR: * add* r> create
180     swap c-getter 0 add* define-inline ;
181
182 : define-out ( name vocab -- )
183     over [ <c-object> tuck 0 ] over c-setter append swap
184     >r >r constructor-word r> r> add* define-inline ;
185
186 : >c-array ( seq type word -- )
187     >r >r dup length dup r> <c-array> dup -roll r>
188     [ execute ] 2curry 2each ; inline
189
190 : >c-array-quot ( type vocab -- quot )
191     dupd set-nth-word [ >c-array ] 2curry ;
192
193 : to-array-word ( name vocab -- word )
194     >r ">c-" swap "-array" 3append r> create ;
195
196 : define-to-array ( type vocab -- )
197     [ to-array-word ] 2keep >c-array-quot define-compound ;
198
199 : c-array>quot ( type vocab -- quot )
200     [
201         \ swap ,
202         nth-word 1quotation ,
203         [ curry map ] %
204     ] [ ] make ;
205
206 : from-array-word ( name vocab -- word )
207     >r "c-" swap "-array>" 3append r> create ;
208
209 : define-from-array ( type vocab -- )
210     [ from-array-word ] 2keep c-array>quot define-compound ;
211
212 : <primitive-type> ( getter setter width boxer unboxer -- type )
213     <c-type>
214     [ set-c-type-unboxer ] keep
215     [ set-c-type-boxer ] keep
216     [ set-c-type-size ] 2keep
217     [ set-c-type-align ] keep
218     [ set-c-type-setter ] keep
219     [ set-c-type-getter ] keep ;
220
221 : define-primitive-type ( type name -- )
222     "alien.c-types"
223     [ define-c-type ] 2keep
224     [ define-deref ] 2keep
225     [ define-to-array ] 2keep
226     [ define-from-array ] 2keep
227     define-out ;
228
229 : expand-constants ( c-type -- c-type' )
230     dup array? [
231         unclip >r [ dup word? [ execute ] when ] map r> add*
232     ] when ;
233
234 [ alien-cell ]
235 [ set-alien-cell ]
236 bootstrap-cell
237 "box_alien"
238 "alien_offset" <primitive-type>
239 "void*" define-primitive-type
240
241 [ alien-signed-8 ]
242 [ set-alien-signed-8 ]
243 8
244 "box_signed_8"
245 "to_signed_8" <primitive-type> <long-long-type>
246 "longlong" define-primitive-type
247
248 [ alien-unsigned-8 ]
249 [ set-alien-unsigned-8 ]
250 8
251 "box_unsigned_8"
252 "to_unsigned_8" <primitive-type> <long-long-type>
253 "ulonglong" define-primitive-type
254
255 [ alien-signed-cell ]
256 [ set-alien-signed-cell ]
257 bootstrap-cell
258 "box_signed_cell"
259 "to_fixnum" <primitive-type>
260 "long" define-primitive-type
261
262 [ alien-unsigned-cell ]
263 [ set-alien-unsigned-cell ]
264 bootstrap-cell
265 "box_unsigned_cell"
266 "to_cell" <primitive-type>
267 "ulong" define-primitive-type
268
269 [ alien-signed-4 ]
270 [ set-alien-signed-4 ]
271 4
272 "box_signed_4"
273 "to_fixnum" <primitive-type>
274 "int" define-primitive-type
275
276 [ alien-unsigned-4 ]
277 [ set-alien-unsigned-4 ]
278 4
279 "box_unsigned_4"
280 "to_cell" <primitive-type>
281 "uint" define-primitive-type
282
283 [ alien-signed-2 ]
284 [ set-alien-signed-2 ]
285 2
286 "box_signed_2"
287 "to_fixnum" <primitive-type>
288 "short" define-primitive-type
289
290 [ alien-unsigned-2 ]
291 [ set-alien-unsigned-2 ]
292 2
293 "box_unsigned_2"
294 "to_cell" <primitive-type>
295 "ushort" define-primitive-type
296
297 [ alien-signed-1 ]
298 [ set-alien-signed-1 ]
299 1
300 "box_signed_1"
301 "to_fixnum" <primitive-type>
302 "char" define-primitive-type
303
304 [ alien-unsigned-1 ]
305 [ set-alien-unsigned-1 ]
306 1
307 "box_unsigned_1"
308 "to_cell" <primitive-type>
309 "uchar" define-primitive-type
310
311 [ alien-unsigned-4 zero? not ]
312 [ 1 0 ? set-alien-unsigned-4 ]
313 4
314 "box_boolean"
315 "to_boolean" <primitive-type>
316 "bool" define-primitive-type
317
318 [ alien-float ]
319 [ >r >r >float r> r> set-alien-float ]
320 4
321 "box_float"
322 "to_float" <primitive-type>
323 "float" define-primitive-type
324
325 T{ float-regs f 4 } "float" c-type set-c-type-reg-class
326 [ >float ] "float" c-type set-c-type-prep
327
328 [ alien-double ]
329 [ >r >r >float r> r> set-alien-double ]
330 8
331 "box_double"
332 "to_double" <primitive-type>
333 "double" define-primitive-type
334
335 T{ float-regs f 8 } "double" c-type set-c-type-reg-class
336 [ >float ] "double" c-type set-c-type-prep
337
338 [ alien-cell alien>char-string ]
339 [ set-alien-cell ]
340 bootstrap-cell
341 "box_char_string"
342 "alien_offset" <primitive-type>
343 "char*" define-primitive-type
344
345 "char*" "uchar*" typedef
346
347 [ string>char-alien ] "char*" c-type set-c-type-prep
348
349 [ alien-cell alien>u16-string ]
350 [ set-alien-cell ]
351 4
352 "box_u16_string"
353 "alien_offset" <primitive-type>
354 "ushort*" define-primitive-type
355
356 [ string>u16-alien ] "ushort*" c-type set-c-type-prep