]> gitweb.factorcode.org Git - factor.git/blob - basis/alien/fortran/fortran.factor
Remove many uses of <int> and *int etc
[factor.git] / basis / alien / fortran / fortran.factor
1 ! (c) 2009 Joe Groff, see BSD license
2 USING: accessors alien alien.complex alien.c-types alien.data
3 alien.parser grouping alien.strings alien.syntax arrays ascii
4 assocs byte-arrays combinators combinators.short-circuit fry
5 generalizations kernel lexer macros math math.parser namespaces
6 parser sequences sequences.generalizations splitting
7 stack-checker vectors vocabs.parser words locals
8 io.encodings.ascii io.encodings.string shuffle effects
9 math.ranges math.order sorting strings system alien.libraries ;
10 QUALIFIED-WITH: alien.c-types c
11 IN: alien.fortran
12
13 SINGLETONS: f2c-abi g95-abi gfortran-abi intel-unix-abi intel-windows-abi ;
14
15 << 
16 : add-f2c-libraries ( -- )
17     "I77" "libI77.so" cdecl add-library
18     "F77" "libF77.so" cdecl add-library ;
19
20 os netbsd? [ add-f2c-libraries ] when
21 >>
22
23 : alien>nstring ( alien len encoding -- string )
24     [ memory>byte-array ] dip decode ;
25
26 ERROR: invalid-fortran-type type ;
27
28 DEFER: fortran-sig>c-sig
29 DEFER: fortran-ret-type>c-type
30 DEFER: fortran-arg-type>c-type
31 DEFER: fortran-name>symbol-name
32
33 SYMBOL: library-fortran-abis
34 SYMBOL: fortran-abi
35 library-fortran-abis [ H{ } clone ] initialize
36
37 <PRIVATE
38
39 : lowercase-name-with-underscore ( name -- name' )
40     >lower "_" append ;
41 : lowercase-name-with-extra-underscore ( name -- name' )
42     >lower CHAR: _ over member? 
43     [ "__" append ] [ "_" append ] if ;
44
45 HOOK: fortran-c-abi fortran-abi ( -- abi )
46 M: f2c-abi fortran-c-abi cdecl ;
47 M: g95-abi fortran-c-abi cdecl ;
48 M: gfortran-abi fortran-c-abi cdecl ;
49 M: intel-unix-abi fortran-c-abi cdecl ;
50 M: intel-windows-abi fortran-c-abi cdecl ;
51
52 HOOK: real-functions-return-double? fortran-abi ( -- ? )
53 M: f2c-abi real-functions-return-double? t ;
54 M: g95-abi real-functions-return-double? f ;
55 M: gfortran-abi real-functions-return-double? f ;
56 M: intel-unix-abi real-functions-return-double? f ;
57 M: intel-windows-abi real-functions-return-double? f ;
58
59 HOOK: complex-functions-return-by-value? fortran-abi ( -- ? )
60 M: f2c-abi complex-functions-return-by-value? f ;
61 M: g95-abi complex-functions-return-by-value? f ;
62 M: gfortran-abi complex-functions-return-by-value? t ;
63 M: intel-unix-abi complex-functions-return-by-value? f ;
64 M: intel-windows-abi complex-functions-return-by-value? f ;
65
66 HOOK: character(1)-maps-to-char? fortran-abi ( -- ? )
67 M: f2c-abi character(1)-maps-to-char? f ;
68 M: g95-abi character(1)-maps-to-char? f ;
69 M: gfortran-abi character(1)-maps-to-char? f ;
70 M: intel-unix-abi character(1)-maps-to-char? t ;
71 M: intel-windows-abi character(1)-maps-to-char? t ;
72
73 HOOK: mangle-name fortran-abi ( name -- name' )
74 M: f2c-abi mangle-name lowercase-name-with-extra-underscore ;
75 M: g95-abi mangle-name lowercase-name-with-extra-underscore ;
76 M: gfortran-abi mangle-name lowercase-name-with-underscore ;
77 M: intel-unix-abi mangle-name lowercase-name-with-underscore ;
78 M: intel-windows-abi mangle-name >upper ;
79
80 TUPLE: fortran-type dims size out? ;
81
82 TUPLE: number-type < fortran-type ;
83 TUPLE: integer-type < number-type ;
84 TUPLE: logical-type < integer-type ;
85 TUPLE: real-type < number-type ;
86 TUPLE: double-precision-type < number-type ;
87
88 TUPLE: character-type < fortran-type ;
89 TUPLE: misc-type < fortran-type name ;
90
91 TUPLE: complex-type < number-type ;
92 TUPLE: real-complex-type < complex-type ;
93 TUPLE: double-complex-type < complex-type ;
94
95 CONSTANT: fortran>c-types H{
96     { "character"        character-type        }
97     { "integer"          integer-type          }
98     { "logical"          logical-type          }
99     { "real"             real-type             }
100     { "double-precision" double-precision-type }
101     { "complex"          real-complex-type     }
102     { "double-complex"   double-complex-type   }
103 }
104
105 : append-dimensions ( base-c-type type -- c-type )
106     dims>> [ product 2array ] when* ;
107
108 MACRO: size-case-type ( cases -- )
109     [ invalid-fortran-type ] suffix
110     '[ [ size>> _ case ] [ append-dimensions ] bi ] ;
111
112 : simple-type ( type base-c-type -- c-type )
113     swap
114     [ dup size>> [ invalid-fortran-type ] [ drop ] if ]
115     [ append-dimensions ] bi ;
116
117 : new-fortran-type ( out? dims size class -- type )
118     new [ [ size<< ] [ dims<< ] [ out?<< ] tri ] keep ;
119
120 GENERIC: (fortran-type>c-type) ( type -- c-type )
121
122 M: f (fortran-type>c-type) drop c:void ;
123
124 M: integer-type (fortran-type>c-type)
125     {
126         { f [ c:int      ] }
127         { 1 [ c:char     ] }
128         { 2 [ c:short    ] }
129         { 4 [ c:int      ] }
130         { 8 [ c:longlong ] }
131     } size-case-type ;
132 M: real-type (fortran-type>c-type)
133     {
134         { f [ c:float  ] }
135         { 4 [ c:float  ] }
136         { 8 [ c:double ] }
137     } size-case-type ;
138 M: real-complex-type (fortran-type>c-type)
139     {
140         {  f [ complex-float  ] }
141         {  8 [ complex-float  ] }
142         { 16 [ complex-double ] }
143     } size-case-type ;
144
145 M: double-precision-type (fortran-type>c-type)
146     c:double simple-type ;
147 M: double-complex-type (fortran-type>c-type)
148     complex-double simple-type ;
149 M: misc-type (fortran-type>c-type)
150     dup name>> parse-c-type simple-type ;
151
152 : single-char? ( character-type -- ? )
153     { [ drop character(1)-maps-to-char? ] [ dims>> product 1 = ] } 1&& ;
154
155 : fix-character-type ( character-type -- character-type' )
156     clone dup size>>
157     [ dup dims>> [ invalid-fortran-type ] [ dup size>> 1array >>dims f >>size ] if ]
158     [ dup dims>> [ ] [ f >>dims ] if ] if
159     dup single-char? [ f >>dims ] when ;
160
161 M: character-type (fortran-type>c-type)
162     fix-character-type c:char simple-type ;
163
164 : dimension>number ( string -- number )
165     dup "*" = [ drop 0 ] [ string>number ] if ;
166
167 : parse-out ( string -- string' out? )
168     "!" ?head ;
169
170 : parse-dims ( string -- string' dim )
171     "(" split1 dup
172     [ ")" ?tail drop "," split [ [ blank? ] trim dimension>number ] map ] when ;
173
174 : parse-size ( string -- string' size )
175     "*" split1 dup [ string>number ] when ;
176
177 : (parse-fortran-type) ( fortran-type-string -- type )
178     parse-out swap parse-dims swap parse-size swap
179     >lower fortran>c-types ?at
180     [ new-fortran-type ] [ misc-type boa ] if ;
181
182 : parse-fortran-type ( fortran-type-string/f -- type/f )
183     dup [ (parse-fortran-type) ] when ;
184
185 GENERIC: added-c-args ( type -- args )
186
187 M: fortran-type added-c-args drop { } ;
188 M: character-type added-c-args fix-character-type single-char? [ { } ] [ { c:long } ] if ;
189
190 GENERIC: returns-by-value? ( type -- ? )
191
192 M: f returns-by-value? drop t ;
193 M: fortran-type returns-by-value? drop f ;
194 M: number-type returns-by-value? dims>> not ;
195 M: character-type returns-by-value? fix-character-type single-char? ;
196 M: complex-type returns-by-value?
197     { [ drop complex-functions-return-by-value? ] [ dims>> not ] } 1&& ;
198
199 GENERIC: (fortran-ret-type>c-type) ( type -- c-type )
200
201 M: f (fortran-ret-type>c-type) drop c:void ;
202 M: fortran-type (fortran-ret-type>c-type) (fortran-type>c-type) ;
203 M: real-type (fortran-ret-type>c-type)
204     drop real-functions-return-double? [ c:double ] [ c:float ] if ;
205
206 GENERIC: (fortran-arg>c-args) ( type -- main-quot added-quot )
207
208 : args?dims ( type quot -- main-quot added-quot )
209     [ dup dims>> [ drop [ ] [ drop ] ] ] dip if ; inline
210
211 M: integer-type (fortran-arg>c-args)
212     [
213         size>> {
214             { f [ [ c:int <ref>     ] [ drop ] ] }
215             { 1 [ [ c:char <ref>    ] [ drop ] ] }
216             { 2 [ [ c:short <ref>   ] [ drop ] ] }
217             { 4 [ [ c:int <ref>     ] [ drop ] ] }
218             { 8 [ [ c:longlong <ref> ] [ drop ] ] }
219             [ invalid-fortran-type ]
220         } case
221     ] args?dims ;
222
223 M: logical-type (fortran-arg>c-args)
224     [ call-next-method [ [ 1 0 ? ] prepend ] dip ] args?dims ;
225
226 M: real-type (fortran-arg>c-args)
227     [
228         size>> {
229             { f [ [ c:float <ref> ] [ drop ] ] }
230             { 4 [ [ c:float <ref> ] [ drop ] ] }
231             { 8 [ [ c:double <ref> ] [ drop ] ] }
232             [ invalid-fortran-type ]
233         } case
234     ] args?dims ;
235
236 M: real-complex-type (fortran-arg>c-args)
237     [
238         size>> {
239             {  f [ [ <complex-float>  ] [ drop ] ] }
240             {  8 [ [ <complex-float>  ] [ drop ] ] }
241             { 16 [ [ <complex-double> ] [ drop ] ] }
242             [ invalid-fortran-type ]
243         } case
244     ] args?dims ;
245
246 M: double-precision-type (fortran-arg>c-args)
247     [ drop [ c:double <ref> ] [ drop ] ] args?dims ;
248
249 M: double-complex-type (fortran-arg>c-args)
250     [ drop [ <complex-double> ] [ drop ] ] args?dims ;
251
252 M: character-type (fortran-arg>c-args)
253     fix-character-type single-char?
254     [ [ first c:char <ref> ] [ drop ] ]
255     [ [ ascii string>alien ] [ length ] ] if ;
256
257 M: misc-type (fortran-arg>c-args)
258     drop [ ] [ drop ] ;
259
260 GENERIC: (fortran-result>) ( type -- quots )
261
262 : result?dims ( type quot -- quot )
263     [ dup dims>> [ drop { [ ] } ] ] dip if ; inline
264
265 M: integer-type (fortran-result>)
266     [
267         size>> {
268             { f [ { [ c:int deref      ] } ] }
269             { 1 [ { [ c:char deref     ] } ] }
270             { 2 [ { [ c:short deref    ] } ] }
271             { 4 [ { [ c:int deref      ] } ] }
272             { 8 [ { [ c:longlong deref ] } ] }
273             [ invalid-fortran-type ]
274         } case
275     ] result?dims ;
276
277 M: logical-type (fortran-result>)
278     [ call-next-method first [ zero? not ] append 1array ] result?dims ;
279
280 M: real-type (fortran-result>)
281     [ size>> {
282         { f [ { [ c:float deref ] } ] }
283         { 4 [ { [ c:float deref ] } ] }
284         { 8 [ { [ c:double deref ] } ] }
285         [ invalid-fortran-type ]
286     } case ] result?dims ;
287
288 M: real-complex-type (fortran-result>)
289     [ size>> {
290         {  f [ { [ *complex-float  ] } ] }
291         {  8 [ { [ *complex-float  ] } ] }
292         { 16 [ { [ *complex-double ] } ] }
293         [ invalid-fortran-type ]
294     } case ] result?dims ;
295
296 M: double-precision-type (fortran-result>)
297     [ drop { [ c:double deref ] } ] result?dims ;
298
299 M: double-complex-type (fortran-result>)
300     [ drop { [ *complex-double ] } ] result?dims ;
301
302 M: character-type (fortran-result>)
303     fix-character-type single-char?
304     [ { [ c:char deref 1string ] } ]
305     [ { [ ] [ ascii alien>nstring ] } ] if ;
306
307 M: misc-type (fortran-result>)
308     drop { [ ] } ;
309
310 GENERIC: (<fortran-result>) ( type -- quot )
311
312 M: fortran-type (<fortran-result>) 
313     (fortran-type>c-type) \ <c-object> [ ] 2sequence ;
314
315 M: character-type (<fortran-result>)
316     fix-character-type dims>> product dup
317     [ \ <byte-array> ] dip [ ] 3sequence ;
318
319 : [<fortran-result>] ( return parameters -- quot )
320     [ parse-fortran-type ] dip
321     over returns-by-value?
322     [ 2drop [ ] ]
323     [ [ (<fortran-result>) ] [ length \ ndip [ ] 3sequence ] bi* ] if ;
324
325 : [fortran-args>c-args] ( parameters -- quot )
326     [ [ ] ] [
327         [ parse-fortran-type (fortran-arg>c-args) 2array ] map flip first2
328         [ [ \ spread [ ] 2sequence ] bi@ 2array ] [ length ] bi 
329         \ ncleave [ ] 3sequence
330     ] if-empty ;
331
332 :: [fortran-invoke] ( [args>args] return library function parameters -- [args>args] quot ) 
333     return parameters fortran-sig>c-sig :> ( c-return c-parameters )
334     function fortran-name>symbol-name :> c-function
335     [args>args] 
336     c-return library c-function c-parameters \ alien-invoke
337     5 [ ] nsequence
338     c-parameters length \ nkeep
339     [ ] 3sequence ;
340
341 : [fortran-out-param>] ( parameter -- quot )
342     parse-fortran-type
343     [ (fortran-result>) ] [ out?>> ] bi
344     [ ] [ [ drop [ drop ] ] map ] if ;
345
346 : [fortran-return>] ( return -- quot )
347     parse-fortran-type {
348         { [ dup not ] [ drop { } ] }
349         { [ dup returns-by-value? ] [ drop { [ ] } ] }
350         [ (fortran-result>) ]
351     } cond ;
352
353 : letters ( -- seq ) CHAR: a CHAR: z [a,b] ;
354
355 : (shuffle-map) ( return parameters -- ret par )
356     [
357         fortran-ret-type>c-type length swap void? [ 1 + ] unless
358         letters swap head [ "ret" swap suffix ] map
359     ] [
360         [ fortran-arg-type>c-type nip length 1 + ] map letters swap zip
361         [ first2 letters swap head [ "" 2sequence ] with map ] map concat
362     ] bi* ;
363
364 : (fortran-in-shuffle) ( ret par -- seq )
365     [ second ] sort-with append ;
366
367 : (fortran-out-shuffle) ( ret par -- seq )
368     append ;
369
370 : [fortran-result-shuffle] ( return parameters -- quot )
371     (shuffle-map) [ (fortran-in-shuffle) ] [ (fortran-out-shuffle) ] 2bi <effect>
372     \ shuffle-effect [ ] 2sequence ;
373
374 : [fortran-results>] ( return parameters -- quot )
375     [ [fortran-result-shuffle] ]
376     [ drop [fortran-return>] ]
377     [ nip [ [fortran-out-param>] ] map concat ] 2tri
378     append
379     \ spread [ ] 2sequence append ;
380
381 : (add-fortran-library) ( fortran-abi name -- )
382     library-fortran-abis get-global set-at ;
383
384 PRIVATE>
385
386 : add-fortran-library ( name soname fortran-abi -- )
387     [ fortran-abi [ fortran-c-abi ] with-variable add-library ]
388     [ nip swap (add-fortran-library) ] 3bi ;
389
390 : fortran-name>symbol-name ( fortran-name -- c-name )
391     mangle-name ;
392
393 : fortran-type>c-type ( fortran-type -- c-type )
394     parse-fortran-type (fortran-type>c-type) ;
395
396 : fortran-arg-type>c-type ( fortran-type -- c-type added-args )
397     parse-fortran-type
398     [ (fortran-type>c-type) <pointer> ]
399     [ added-c-args ] bi ;
400 : fortran-ret-type>c-type ( fortran-type -- c-type added-args )
401     parse-fortran-type dup returns-by-value?
402     [ (fortran-ret-type>c-type) { } ] [
403         c:void swap 
404         [ added-c-args ] [ (fortran-type>c-type) <pointer> ] bi prefix
405     ] if ;
406
407 : fortran-arg-types>c-types ( fortran-types -- c-types )
408     [ length <vector> 1 <vector> ] keep
409     [ fortran-arg-type>c-type swapd [ suffix! ] [ append! ] 2bi* ] each
410     append >array ;
411
412 : fortran-sig>c-sig ( fortran-return fortran-args -- c-return c-args )
413     [ fortran-ret-type>c-type ] [ fortran-arg-types>c-types ] bi* append ;
414
415 : set-fortran-abi ( library -- )
416     library-fortran-abis get-global at fortran-abi set ;
417
418 : (fortran-invoke) ( return library function parameters -- quot )
419     {
420         [ 2nip [<fortran-result>] ]
421         [ nip nip nip [fortran-args>c-args] ]
422         [ [fortran-invoke] ]
423         [ 2nip [fortran-results>] ]
424     } 4 ncleave 4 nappend ;
425
426 MACRO: fortran-invoke ( return library function parameters -- )
427     { [ 2drop nip set-fortran-abi ] [ (fortran-invoke) ] } 4 ncleave ;
428
429 : parse-arglist ( parameters return -- types effect )
430     [ 2 group unzip [ "," ?tail drop ] map ]
431     [ [ { } ] [ 1array ] if-void ]
432     bi* <effect> ;
433
434 :: define-fortran-function ( return library function parameters -- )
435     function create-in dup reset-generic 
436     return library function parameters return [ c:void ] unless* parse-arglist
437     [ \ fortran-invoke 5 [ ] nsequence ] dip define-declared ;
438
439 SYNTAX: SUBROUTINE: 
440     f current-library get scan ";" parse-tokens
441     [ "()" subseq? not ] filter define-fortran-function ;
442
443 SYNTAX: FUNCTION:
444     scan current-library get scan ";" parse-tokens
445     [ "()" subseq? not ] filter define-fortran-function ;
446
447 SYNTAX: LIBRARY:
448     scan
449     [ current-library set ]
450     [ set-fortran-abi ] bi ;
451