]> gitweb.factorcode.org Git - factor.git/blob - extra/python/python.factor
core/basis/extra: using STARTUP-HOOK: and SHUTDOWN-HOOK:
[factor.git] / extra / python / python.factor
1 USING: alien alien.libraries arrays assocs byte-arrays
2 hashtables init kernel math math.parser namespaces python.errors
3 python.ffi python.objects sequences strings vectors ;
4
5 IN: python
6
7 ERROR: python-error type message traceback ;
8
9 ! Initialization and finalization
10 : py-initialize ( -- )
11     Py_IsInitialized [ Py_Initialize ] unless ;
12
13 : py-finalize ( -- )
14     Py_IsInitialized [ Py_Finalize ] when ;
15
16 ! Importing
17 : py-import ( modulename -- module )
18     PyImport_ImportModule check-new-ref ;
19
20 : py-import-from ( modulename objname -- obj )
21     [ py-import ] [ getattr ] bi* ;
22
23 ! Data marshalling to Python
24 : array>py-tuple ( array -- py-tuple )
25     [ length <py-tuple> ] keep
26     [ [ dup ] 2dip swap py-tuple-set-item ] each-index ;
27
28 : vector>py-list ( vector -- py-list )
29     [ length <py-list> ] keep
30     [ [ dup ] 2dip swap py-list-set-item ] each-index ;
31
32 : assoc>py-dict ( assoc -- py-dict )
33     <py-dict> swap [ [ dup ] 2dip py-dict-set-item ] assoc-each ;
34
35 : py-tuple>array ( py-tuple -- arr )
36     dup py-tuple-size <iota> [ py-tuple-get-item ] with map ;
37
38 : py-list>vector ( py-list -- vector )
39     dup py-list-size <iota> [ py-list-get-item ] with V{ } map-as ;
40
41 : py-unicode>string ( py-unicode -- string )
42     PyUnicode_AsUTF8 (check-ref) ;
43
44 : py-bytes>byte-array ( py-bytes -- byte-array )
45     PyBytes_AsString (check-ref) >byte-array ;
46
47 : py-dict>hashtable ( py-dict -- hashtable )
48     PyDict_Items (check-ref) py-list>vector
49     [ py-tuple>array ] map >hashtable ;
50
51 : py-class-name ( py-object -- name )
52     "__class__" getattr "__name__" getattr py-unicode>string ;
53
54 GENERIC: >py ( obj -- py-obj )
55
56 M: byte-array >py
57     dup length PyBytes_FromStringAndSize check-new-ref ;
58
59 M: string >py
60     PyUnicode_FromString check-new-ref ;
61
62 M: math:fixnum >py
63     PyLong_FromLong check-new-ref ;
64
65 M: math:bignum >py
66     number>string f 10 PyLong_FromString check-new-ref ;
67
68 M: math:float >py
69     PyFloat_FromDouble check-new-ref ;
70
71 M: array >py
72     [ >py ] map array>py-tuple ;
73
74 M: hashtable >py
75     [ [ >py ] bi@ ] assoc-map assoc>py-dict ;
76
77 M: vector >py
78     [ >py ] map vector>py-list ;
79
80 M: f >py
81     drop <none> ;
82
83 ! Data marshalling to Factor
84 SYMBOL: py-type-dispatch
85
86 DEFER: py>
87
88 : init-py-type-dispatch ( -- table )
89     H{
90         { "NoneType" [ drop f ] }
91         { "bool" [ PyObject_IsTrue 1 = ] }
92         { "bytes" [ py-bytes>byte-array ] }
93         { "dict" [ py-dict>hashtable [ [ py> ] bi@ ] assoc-map ] }
94         { "int" [ PyLong_AsLong ] }
95         { "list" [ py-list>vector [ py> ] map ] }
96         { "str" [ py-unicode>string ] }
97         { "tuple" [ py-tuple>array [ py> ] map ] }
98     } clone ;
99
100 py-type-dispatch [ init-py-type-dispatch ] initialize
101
102 ERROR: missing-type type ;
103
104 : py> ( py-obj -- obj )
105     dup py-class-name py-type-dispatch get ?at
106     [ call( x -- x ) ] [ missing-type ] if ;
107
108 ! Callbacks
109 : quot>py-callback ( quot: ( args kw -- ret ) -- alien )
110     '[ nipd [ [ py> ] [ { } ] if* ] bi@ @ >py ] PyCallback ; inline
111
112 : with-quot>py-cfunction ( alien quot -- )
113     '[ <py-cfunction> @ ] with-callback ; inline
114
115 : python-dll-loaded? ( -- ? )
116     "Py_IsInitialized" "python" dlsym? ;
117
118 STARTUP-HOOK: [ python-dll-loaded? [ py-initialize ] when ]
119 SHUTDOWN-HOOK: [ python-dll-loaded? [ py-finalize ] when ]