python: vocab split into subvocabs python.errors and python.objects for
easier maintenancedb4
							parent
							
								
									eb612e25b0
								
							
						
					
					
						commit
						ac28527d53
					
				| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
IN: python.errors
 | 
			
		||||
USING: python.errors help.markup help.syntax ;
 | 
			
		||||
 | 
			
		||||
HELP: check-zero
 | 
			
		||||
{ $description
 | 
			
		||||
  "Verifies that the return code is 0 and throws an error otherwise."
 | 
			
		||||
} ;
 | 
			
		||||
 | 
			
		||||
HELP: (check-ref)
 | 
			
		||||
{ $description
 | 
			
		||||
  "Verifies that the reference is not f and throws an error if it is."
 | 
			
		||||
} ;
 | 
			
		||||
 | 
			
		||||
HELP: check-new-ref
 | 
			
		||||
{ $description
 | 
			
		||||
  "Adds reference counting to the returned python object which is assumed to be a new reference. An error is thrown if the object is f. This word is used to wrap Python functions that return new references."
 | 
			
		||||
} ;
 | 
			
		||||
 | 
			
		||||
HELP: check-borrowed-ref
 | 
			
		||||
{ $description
 | 
			
		||||
  "Adds reference counting to the returned python object which is assumed to be a borrowed reference. An error is thrown if the object is f. This word is used to wrap Python functions that return borrowed references."
 | 
			
		||||
} ;
 | 
			
		||||
 | 
			
		||||
HELP: unsteal-ref
 | 
			
		||||
{ $description
 | 
			
		||||
  "Increases the objects reference count. Used by wrappers that call Python functions that steal references."
 | 
			
		||||
} ;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
USING: alien.c-types alien.data kernel python.ffi ;
 | 
			
		||||
IN: python.errors
 | 
			
		||||
 | 
			
		||||
ERROR: python-error type message ;
 | 
			
		||||
 | 
			
		||||
<PRIVATE
 | 
			
		||||
 | 
			
		||||
: get-error ( -- ptype pvalue )
 | 
			
		||||
    { void* void* void* } [ PyErr_Fetch ] with-out-parameters drop ;
 | 
			
		||||
 | 
			
		||||
: throw-error ( ptype pvalue -- )
 | 
			
		||||
    [ "__name__" PyObject_GetAttrString ] [ PyObject_Str ] bi*
 | 
			
		||||
    [ &Py_DecRef PyString_AsString ] bi@ python-error ;
 | 
			
		||||
 | 
			
		||||
PRIVATE>
 | 
			
		||||
 | 
			
		||||
: (check-ref) ( ref -- ref' )
 | 
			
		||||
    [ get-error throw-error f ] unless* ;
 | 
			
		||||
 | 
			
		||||
: check-new-ref ( ref -- ref' )
 | 
			
		||||
    &Py_DecRef (check-ref) ;
 | 
			
		||||
 | 
			
		||||
: check-borrowed-ref ( ref -- ref' )
 | 
			
		||||
    dup Py_IncRef &Py_DecRef (check-ref) ;
 | 
			
		||||
 | 
			
		||||
: check-zero ( code -- )
 | 
			
		||||
    0 = [ get-error throw-error ] unless ;
 | 
			
		||||
 | 
			
		||||
: unsteal-ref ( ref -- ref' )
 | 
			
		||||
    dup Py_IncRef ;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
Error handling and reference counting
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,60 @@
 | 
			
		|||
USING: alien.c-types alien.data kernel python.errors python.ffi ;
 | 
			
		||||
IN: python.objects
 | 
			
		||||
 | 
			
		||||
! Objects
 | 
			
		||||
: getattr ( obj str -- value )
 | 
			
		||||
    PyObject_GetAttrString check-new-ref ;
 | 
			
		||||
 | 
			
		||||
: setattr ( obj str value -- )
 | 
			
		||||
    PyObject_SetAttrString check-zero ;
 | 
			
		||||
 | 
			
		||||
: call-object ( obj args -- value )
 | 
			
		||||
    PyObject_CallObject check-new-ref ;
 | 
			
		||||
 | 
			
		||||
: call-object-full ( obj args kwargs -- value )
 | 
			
		||||
    PyObject_Call check-new-ref ;
 | 
			
		||||
 | 
			
		||||
! Tuples
 | 
			
		||||
: <py-tuple> ( length -- tuple )
 | 
			
		||||
    PyTuple_New check-new-ref ;
 | 
			
		||||
 | 
			
		||||
: py-tuple-set-item ( obj pos val -- )
 | 
			
		||||
    unsteal-ref PyTuple_SetItem check-zero ;
 | 
			
		||||
 | 
			
		||||
: py-tuple-get-item ( obj pos -- val )
 | 
			
		||||
    PyTuple_GetItem dup Py_IncRef check-new-ref ;
 | 
			
		||||
 | 
			
		||||
: py-tuple-size ( obj -- len )
 | 
			
		||||
    PyTuple_Size ;
 | 
			
		||||
 | 
			
		||||
: <1py-tuple> ( alien -- tuple )
 | 
			
		||||
    1 <py-tuple> [ 0 rot py-tuple-set-item ] keep ;
 | 
			
		||||
 | 
			
		||||
! Dicts
 | 
			
		||||
: <py-dict> ( -- dict )
 | 
			
		||||
    PyDict_New check-new-ref ;
 | 
			
		||||
 | 
			
		||||
: py-dict-set-item ( obj key val -- )
 | 
			
		||||
    PyDict_SetItem check-zero ;
 | 
			
		||||
 | 
			
		||||
: py-dict-set-item-string ( dict key val -- )
 | 
			
		||||
    PyDict_SetItemString check-zero ;
 | 
			
		||||
 | 
			
		||||
: py-dict-get-item-string ( obj key -- val )
 | 
			
		||||
    PyDict_GetItemString check-borrowed-ref ;
 | 
			
		||||
 | 
			
		||||
: py-dict-size ( obj -- len )
 | 
			
		||||
    PyDict_Size ;
 | 
			
		||||
 | 
			
		||||
! Lists
 | 
			
		||||
: <py-list> ( length -- list )
 | 
			
		||||
    PyList_New check-new-ref ;
 | 
			
		||||
 | 
			
		||||
: py-list-size ( list -- len )
 | 
			
		||||
    PyList_Size ;
 | 
			
		||||
 | 
			
		||||
: py-list-get-item ( obj pos -- val )
 | 
			
		||||
    PyList_GetItem check-borrowed-ref ;
 | 
			
		||||
 | 
			
		||||
: py-list-set-item ( obj pos val -- )
 | 
			
		||||
    unsteal-ref PyList_SetItem check-zero ;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
IN: python
 | 
			
		||||
USING: python help.markup help.syntax ;
 | 
			
		||||
 | 
			
		||||
ARTICLE: "python" "Python binding"
 | 
			
		||||
"The " { $vocab-link "python" } " vocab and its subvocabs implements a simple binding for libpython, allowing factor code to call native python."
 | 
			
		||||
$nl
 | 
			
		||||
"Initialization and finalization:"
 | 
			
		||||
{ $subsections py-initialize py-finalize }
 | 
			
		||||
"Module management:"
 | 
			
		||||
{ $subsections import } ;
 | 
			
		||||
 | 
			
		||||
HELP: py-initialize
 | 
			
		||||
{ $description "Initializes the python binding. This word must be called before any other words in the api can be used" } ;
 | 
			
		||||
 | 
			
		||||
HELP: py-finalize
 | 
			
		||||
{ $description "Finalizes the python binding. After this word is called the api must not be used anymore." } ;
 | 
			
		||||
 | 
			
		||||
HELP: >py
 | 
			
		||||
{ $values { "obj" "a factor object" } { "py-obj" "a python object" } }
 | 
			
		||||
{ $description "Converts a factor objects to its most fitting python representation." }
 | 
			
		||||
{ $examples
 | 
			
		||||
  { $example
 | 
			
		||||
    "USING: python ;"
 | 
			
		||||
    "10 iota >array >py >factor ."
 | 
			
		||||
    "{ 0 1 2 3 4 5 6 7 8 9 }"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
{ $see-also >factor } ;
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
USING: accessors arrays assocs calendar continuations destructors fry kernel
 | 
			
		||||
math namespaces python python.ffi sequences strings tools.test ;
 | 
			
		||||
math namespaces python python.ffi python.objects sequences strings tools.test ;
 | 
			
		||||
IN: python.tests
 | 
			
		||||
 | 
			
		||||
py-initialize
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
USING: accessors alien alien.c-types alien.data arrays assocs fry
 | 
			
		||||
hashtables kernel namespaces python.ffi sequences strings vectors ;
 | 
			
		||||
USING: accessors alien alien.c-types alien.data arrays assocs fry hashtables
 | 
			
		||||
kernel namespaces python.errors python.ffi python.objects sequences strings
 | 
			
		||||
vectors ;
 | 
			
		||||
IN: python
 | 
			
		||||
QUALIFIED: math
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -10,86 +11,9 @@ QUALIFIED: math
 | 
			
		|||
: py-finalize ( -- )
 | 
			
		||||
    Py_IsInitialized [ Py_Finalize ] when ;
 | 
			
		||||
 | 
			
		||||
! Error handling
 | 
			
		||||
ERROR: python-error type message ;
 | 
			
		||||
 | 
			
		||||
: get-error ( -- ptype pvalue )
 | 
			
		||||
    { void* void* void* } [ PyErr_Fetch ] with-out-parameters drop ;
 | 
			
		||||
 | 
			
		||||
: throw-error ( ptype pvalue -- )
 | 
			
		||||
    [ "__name__" PyObject_GetAttrString ] [ PyObject_Str ] bi* [ &Py_DecRef ] bi@
 | 
			
		||||
    [ PyString_AsString ] bi@ python-error ;
 | 
			
		||||
 | 
			
		||||
: (check-return) ( value/f -- value' )
 | 
			
		||||
    [ get-error throw-error f ] unless* ;
 | 
			
		||||
 | 
			
		||||
: check-return ( value/f -- value' )
 | 
			
		||||
    (check-return) &Py_DecRef ;
 | 
			
		||||
 | 
			
		||||
: check-return-code ( return -- )
 | 
			
		||||
    0 = [ get-error throw-error ] unless ;
 | 
			
		||||
 | 
			
		||||
! Importing
 | 
			
		||||
: import ( str -- module )
 | 
			
		||||
    PyImport_ImportModule check-return ;
 | 
			
		||||
 | 
			
		||||
! Objects
 | 
			
		||||
: getattr ( obj str -- value )
 | 
			
		||||
    PyObject_GetAttrString check-return ;
 | 
			
		||||
 | 
			
		||||
: setattr ( obj str value -- )
 | 
			
		||||
    PyObject_SetAttrString check-return-code ;
 | 
			
		||||
 | 
			
		||||
: call-object ( obj args -- value )
 | 
			
		||||
    PyObject_CallObject check-return ;
 | 
			
		||||
 | 
			
		||||
: call-object-full ( obj args kwargs -- value )
 | 
			
		||||
    PyObject_Call check-return ;
 | 
			
		||||
 | 
			
		||||
! Types
 | 
			
		||||
: <py-tuple> ( length -- tuple )
 | 
			
		||||
    PyTuple_New check-return ;
 | 
			
		||||
 | 
			
		||||
: py-tuple-set-item ( obj pos val -- )
 | 
			
		||||
    dup Py_IncRef PyTuple_SetItem check-return-code ;
 | 
			
		||||
 | 
			
		||||
: py-tuple-get-item ( obj pos -- val )
 | 
			
		||||
    PyTuple_GetItem dup Py_IncRef check-return ;
 | 
			
		||||
 | 
			
		||||
: py-tuple-size ( obj -- len )
 | 
			
		||||
    PyTuple_Size ;
 | 
			
		||||
 | 
			
		||||
: <1py-tuple> ( alien -- tuple )
 | 
			
		||||
    1 <py-tuple> [ 0 rot py-tuple-set-item ] keep ;
 | 
			
		||||
 | 
			
		||||
! Dicts
 | 
			
		||||
: <py-dict> ( -- dict )
 | 
			
		||||
    PyDict_New check-return ;
 | 
			
		||||
 | 
			
		||||
: py-dict-set-item ( obj key val -- )
 | 
			
		||||
    PyDict_SetItem check-return-code ;
 | 
			
		||||
 | 
			
		||||
: py-dict-set-item-string ( dict key val -- )
 | 
			
		||||
    PyDict_SetItemString check-return-code ;
 | 
			
		||||
 | 
			
		||||
: py-dict-get-item-string ( obj key -- val )
 | 
			
		||||
    PyDict_GetItemString dup Py_IncRef check-return ;
 | 
			
		||||
 | 
			
		||||
: py-dict-size ( obj -- len )
 | 
			
		||||
    PyDict_Size ;
 | 
			
		||||
 | 
			
		||||
! Lists
 | 
			
		||||
: <py-list> ( length -- list )
 | 
			
		||||
    PyList_New check-return ;
 | 
			
		||||
 | 
			
		||||
: py-list-size ( list -- len )
 | 
			
		||||
    PyList_Size ;
 | 
			
		||||
 | 
			
		||||
: py-list-get-item ( obj pos -- val )
 | 
			
		||||
    PyList_GetItem dup Py_IncRef check-return ;
 | 
			
		||||
 | 
			
		||||
: py-list-set-item ( obj pos val -- )
 | 
			
		||||
    dup Py_IncRef PyList_SetItem check-return-code ;
 | 
			
		||||
    PyImport_ImportModule check-new-ref ;
 | 
			
		||||
 | 
			
		||||
! Unicodes
 | 
			
		||||
: py-ucs-size ( -- n )
 | 
			
		||||
| 
						 | 
				
			
			@ -98,8 +22,8 @@ ERROR: python-error type message ;
 | 
			
		|||
: py-unicode>utf8 ( uni -- str )
 | 
			
		||||
    py-ucs-size 4 =
 | 
			
		||||
    [ PyUnicodeUCS4_AsUTF8String ]
 | 
			
		||||
    [ PyUnicodeUCS2_AsUTF8String ] if (check-return)
 | 
			
		||||
    PyString_AsString (check-return) ;
 | 
			
		||||
    [ PyUnicodeUCS2_AsUTF8String ] if (check-ref)
 | 
			
		||||
    PyString_AsString (check-ref) ;
 | 
			
		||||
 | 
			
		||||
: utf8>py-unicode ( str -- uni )
 | 
			
		||||
    py-ucs-size 4 =
 | 
			
		||||
| 
						 | 
				
			
			@ -145,11 +69,11 @@ DEFER: >factor
 | 
			
		|||
    H{
 | 
			
		||||
        { "NoneType" [ drop f ] }
 | 
			
		||||
        { "bool" [ PyObject_IsTrue 1 = ] }
 | 
			
		||||
        { "dict" [ PyDict_Items (check-return) >factor >hashtable ] }
 | 
			
		||||
        { "dict" [ PyDict_Items (check-ref) >factor >hashtable ] }
 | 
			
		||||
        { "int" [ PyInt_AsLong ] }
 | 
			
		||||
        { "list" [ py-list>vector [ >factor ] map ] }
 | 
			
		||||
        { "long" [ PyLong_AsLong ] }
 | 
			
		||||
        { "str" [ PyString_AsString (check-return) ] }
 | 
			
		||||
        { "str" [ PyString_AsString (check-ref) ] }
 | 
			
		||||
        { "tuple" [ py-tuple>array [ >factor ] map ] }
 | 
			
		||||
        { "unicode" [ py-unicode>utf8 ] }
 | 
			
		||||
    } clone ;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
USING: arrays assocs destructors fry kernel math namespaces python python.ffi
 | 
			
		||||
python.syntax python.tests sequences sets tools.test ;
 | 
			
		||||
python.objects python.syntax python.tests sequences sets tools.test ;
 | 
			
		||||
IN: python.syntax.tests
 | 
			
		||||
 | 
			
		||||
! Importing functions
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
USING: accessors arrays effects effects.parser fry generalizations
 | 
			
		||||
kernel lexer math namespaces parser python python.ffi sequences
 | 
			
		||||
kernel lexer math namespaces parser python python.ffi python.objects sequences
 | 
			
		||||
sequences.generalizations vocabs.parser words ;
 | 
			
		||||
IN: python.syntax
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue