python.syntax: vocab that makes python functions work like factor words
							parent
							
								
									7b92bad65a
								
							
						
					
					
						commit
						0af4fee085
					
				| 
						 | 
				
			
			@ -71,6 +71,9 @@ FUNCTION: int PyList_Size ( PyObject* t ) ;
 | 
			
		|||
FUNCTION: c-string PyModule_GetName ( PyObject* module ) ;
 | 
			
		||||
FUNCTION: PyObject* PyModule_GetDict ( PyObject* module ) ;
 | 
			
		||||
 | 
			
		||||
! Callables
 | 
			
		||||
FUNCTION: int PyCallable_Check ( PyObject* obj ) ;
 | 
			
		||||
 | 
			
		||||
! Objects
 | 
			
		||||
FUNCTION: PyObject* PyObject_CallObject ( PyObject* callable,
 | 
			
		||||
                                          PyObject* args ) ;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@ USING:
 | 
			
		|||
    fry kernel
 | 
			
		||||
    math
 | 
			
		||||
    namespaces
 | 
			
		||||
    python python.ffi python.stdlib.builtin python.stdlib.sys
 | 
			
		||||
    python python.ffi
 | 
			
		||||
    sequences
 | 
			
		||||
    strings tools.test ;
 | 
			
		||||
IN: python.tests
 | 
			
		||||
| 
						 | 
				
			
			@ -116,31 +116,3 @@ SYMBOLS: year month day ;
 | 
			
		|||
[ t ] [
 | 
			
		||||
    "os" import PyModule_GetDict dup Py_IncRef &Py_DecRef py-dict-size 100 >
 | 
			
		||||
] py-test
 | 
			
		||||
 | 
			
		||||
! Reference counting tests
 | 
			
		||||
[ 2 ] [ 3 <py-tuple> getrefcount >factor ] py-test
 | 
			
		||||
 | 
			
		||||
[ -2 ] [
 | 
			
		||||
    H{ { "foo" 33 } { "bar" 44 } } >py
 | 
			
		||||
    [ "foo" py-dict-get-item-string getrefcount >factor ]
 | 
			
		||||
    [
 | 
			
		||||
        '[
 | 
			
		||||
            500 [ _ "foo" py-dict-get-item-string drop ] times
 | 
			
		||||
        ] with-destructors
 | 
			
		||||
    ]
 | 
			
		||||
    [ "foo" py-dict-get-item-string getrefcount >factor ] tri -
 | 
			
		||||
] py-test
 | 
			
		||||
 | 
			
		||||
[ -2 ] [
 | 
			
		||||
    "abcd" >py <1py-tuple>
 | 
			
		||||
    [ 0 py-tuple-get-item getrefcount >factor ]
 | 
			
		||||
    [
 | 
			
		||||
        [ 100 [ swap 0 py-tuple-get-item drop ] with times ] with-destructors
 | 
			
		||||
    ]
 | 
			
		||||
    [ 0 py-tuple-get-item getrefcount >factor ] tri -
 | 
			
		||||
] py-test
 | 
			
		||||
 | 
			
		||||
! Tests for builtins
 | 
			
		||||
[ 10 ] [ 10 range >factor length ] py-test
 | 
			
		||||
 | 
			
		||||
[ t ] [ "os" import "getpid" getattr callable >factor ] py-test
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -107,21 +107,20 @@ ERROR: python-error type message ;
 | 
			
		|||
    [ PyUnicodeUCS2_FromString ] if ;
 | 
			
		||||
 | 
			
		||||
! Data marshalling to Python
 | 
			
		||||
: array>py-tuple ( arr -- py-tuple )
 | 
			
		||||
    [ length <py-tuple> dup ] keep
 | 
			
		||||
    [ rot py-tuple-set-item ] with each-index ;
 | 
			
		||||
 | 
			
		||||
GENERIC: (>py) ( obj -- obj' )
 | 
			
		||||
M: string (>py) utf8>py-unicode ;
 | 
			
		||||
M: math:fixnum (>py) PyLong_FromLong ;
 | 
			
		||||
M: math:float (>py) PyFloat_FromDouble ;
 | 
			
		||||
 | 
			
		||||
M: array (>py)
 | 
			
		||||
    [ length <py-tuple> dup ] [ [ (>py) ] map ] bi
 | 
			
		||||
    [ rot py-tuple-set-item ] with each-index ;
 | 
			
		||||
 | 
			
		||||
M: array (>py) [ (>py) ] map array>py-tuple ;
 | 
			
		||||
M: hashtable (>py)
 | 
			
		||||
    <py-dict> swap dupd [
 | 
			
		||||
        swapd [ (>py) ] [ (>py) ] bi* py-dict-set-item
 | 
			
		||||
    ] with assoc-each ;
 | 
			
		||||
 | 
			
		||||
! ! I'll make a fast-path for this
 | 
			
		||||
M: word (>py) name>> (>py) ;
 | 
			
		||||
 | 
			
		||||
: >py ( obj -- py-obj )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,26 +0,0 @@
 | 
			
		|||
USING: alien arrays kernel namespaces python ;
 | 
			
		||||
IN: python.stdlib.builtin
 | 
			
		||||
 | 
			
		||||
py-initialize
 | 
			
		||||
 | 
			
		||||
SYMBOL: builtin
 | 
			
		||||
 | 
			
		||||
builtin [ "__builtin__" import ] initialize
 | 
			
		||||
 | 
			
		||||
: simple-call ( arg func-name -- return )
 | 
			
		||||
    builtin get swap getattr swap <1py-tuple> call-object ;
 | 
			
		||||
 | 
			
		||||
: repr ( alien/factor -- py-str )
 | 
			
		||||
    dup alien? [ >py ] unless "repr" simple-call ;
 | 
			
		||||
 | 
			
		||||
: range ( n -- py-list )
 | 
			
		||||
    >py "range" simple-call ;
 | 
			
		||||
 | 
			
		||||
: dir ( obj -- py-list )
 | 
			
		||||
    "dir" simple-call ;
 | 
			
		||||
 | 
			
		||||
: type ( obj -- py-obj )
 | 
			
		||||
    "type" simple-call ;
 | 
			
		||||
 | 
			
		||||
: callable ( obj -- py-obj )
 | 
			
		||||
    "callable" simple-call ;
 | 
			
		||||
| 
						 | 
				
			
			@ -1,10 +0,0 @@
 | 
			
		|||
USING: kernel namespaces python ;
 | 
			
		||||
IN: python.stdlib.sys
 | 
			
		||||
 | 
			
		||||
py-initialize
 | 
			
		||||
 | 
			
		||||
SYMBOL: sys
 | 
			
		||||
sys [ "sys" import ] initialize
 | 
			
		||||
 | 
			
		||||
: getrefcount ( alien -- py-int )
 | 
			
		||||
    <1py-tuple> sys get "getrefcount" getattr swap call-object ;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,81 @@
 | 
			
		|||
USING:
 | 
			
		||||
    assocs
 | 
			
		||||
    destructors
 | 
			
		||||
    fry
 | 
			
		||||
    kernel
 | 
			
		||||
    math
 | 
			
		||||
    namespaces
 | 
			
		||||
    python python.ffi python.syntax python.tests
 | 
			
		||||
    sequences
 | 
			
		||||
    tools.test ;
 | 
			
		||||
IN: python.syntax.tests
 | 
			
		||||
 | 
			
		||||
! Define your own type conversions.
 | 
			
		||||
[ py-date>factor ] "date" py-type-dispatch get set-at
 | 
			
		||||
 | 
			
		||||
! Importing functions
 | 
			
		||||
PY-FROM: os =>
 | 
			
		||||
    getpid ( -- y )
 | 
			
		||||
    system ( x -- y ) ;
 | 
			
		||||
 | 
			
		||||
[ t ] [ getpid integer? ] unit-test
 | 
			
		||||
 | 
			
		||||
! Automatic tuple unpacking
 | 
			
		||||
PY-FROM: os.path =>
 | 
			
		||||
    basename ( x -- x' )
 | 
			
		||||
    splitext ( x -- base ext ) ;
 | 
			
		||||
 | 
			
		||||
[ "hello.doc" ] [ "/some/path/hello.doc" basename ] unit-test
 | 
			
		||||
 | 
			
		||||
[ "hello" ".doc" ] [ "hello.doc" splitext ] unit-test
 | 
			
		||||
 | 
			
		||||
PY-FROM: time => sleep ( n -- ) ;
 | 
			
		||||
 | 
			
		||||
[ ] [ 0 sleep ] unit-test
 | 
			
		||||
 | 
			
		||||
! Module variables are bound as zero-arg functions
 | 
			
		||||
PY-FROM: sys => path ( -- seq ) ;
 | 
			
		||||
 | 
			
		||||
[ t ] [ path sequence? ] unit-test
 | 
			
		||||
 | 
			
		||||
! Use the pipe functions to work on PyObjects.
 | 
			
		||||
PY-FROM: __builtin__ =>
 | 
			
		||||
    callable ( obj -- ? )
 | 
			
		||||
    int ( val -- s )
 | 
			
		||||
    len ( seq -- n )
 | 
			
		||||
    range ( n -- seq ) ;
 | 
			
		||||
 | 
			
		||||
[ t ] [ path| |len| |int 5 > ] unit-test
 | 
			
		||||
 | 
			
		||||
[ 10 ] [ 10 range| |len ] py-test
 | 
			
		||||
 | 
			
		||||
! Callables
 | 
			
		||||
[ t ] [
 | 
			
		||||
    "os" import "getpid" getattr
 | 
			
		||||
    [ |callable ] [ PyCallable_Check 1 = ] bi and
 | 
			
		||||
] py-test
 | 
			
		||||
 | 
			
		||||
! Reference counting
 | 
			
		||||
PY-FROM: sys => getrefcount ( obj -- n ) ;
 | 
			
		||||
 | 
			
		||||
[ 2 ] [ 3 <py-tuple> |getrefcount ] py-test
 | 
			
		||||
 | 
			
		||||
[ -2 ] [
 | 
			
		||||
    H{ { "foo" 33 } { "bar" 44 } } >py
 | 
			
		||||
    [ "foo" py-dict-get-item-string |getrefcount ]
 | 
			
		||||
    [
 | 
			
		||||
        '[
 | 
			
		||||
            500 [ _ "foo" py-dict-get-item-string drop ] times
 | 
			
		||||
        ] with-destructors
 | 
			
		||||
    ]
 | 
			
		||||
    [ "foo" py-dict-get-item-string |getrefcount ] tri -
 | 
			
		||||
] py-test
 | 
			
		||||
 | 
			
		||||
[ -2 ] [
 | 
			
		||||
    "abcd" >py <1py-tuple>
 | 
			
		||||
    [ 0 py-tuple-get-item |getrefcount ]
 | 
			
		||||
    [
 | 
			
		||||
        [ 100 [ swap 0 py-tuple-get-item drop ] with times ] with-destructors
 | 
			
		||||
    ]
 | 
			
		||||
    [ 0 py-tuple-get-item |getrefcount ] tri -
 | 
			
		||||
] py-test
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,62 @@
 | 
			
		|||
USING:
 | 
			
		||||
    accessors
 | 
			
		||||
    arrays
 | 
			
		||||
    effects effects.parser
 | 
			
		||||
    formatting
 | 
			
		||||
    fry
 | 
			
		||||
    generalizations
 | 
			
		||||
    kernel
 | 
			
		||||
    lexer
 | 
			
		||||
    locals
 | 
			
		||||
    namespaces
 | 
			
		||||
    parser
 | 
			
		||||
    python python.ffi
 | 
			
		||||
    sequences sequences.generalizations
 | 
			
		||||
    vocabs.parser
 | 
			
		||||
    words ;
 | 
			
		||||
IN: python.syntax
 | 
			
		||||
 | 
			
		||||
py-initialize
 | 
			
		||||
 | 
			
		||||
SYMBOL: current-module
 | 
			
		||||
 | 
			
		||||
: call-or-eval ( args obj -- ret )
 | 
			
		||||
    dup PyCallable_Check 1 = [ swap call-object ] [ nip ] if ;
 | 
			
		||||
 | 
			
		||||
: factor>factor-quot ( py-function effect -- quot )
 | 
			
		||||
    [ in>> length ] [ out>> length ] bi swapd '[
 | 
			
		||||
        _ narray >py _ call-or-eval >factor
 | 
			
		||||
        _ [ 1 = [ 1array ] when ] [ firstn ] bi
 | 
			
		||||
    ] ;
 | 
			
		||||
 | 
			
		||||
: factor>py-quot ( py-function effect -- quot )
 | 
			
		||||
    in>> length swap '[ _ narray >py _ call-or-eval ] ;
 | 
			
		||||
 | 
			
		||||
: py>factor-quot ( py-function effect -- quot )
 | 
			
		||||
    [ in>> length ] [ out>> length ] bi swapd '[
 | 
			
		||||
        _ narray array>py-tuple _ call-or-eval >factor
 | 
			
		||||
        _ [ 1 = [ 1array ] when ] [ firstn ] bi
 | 
			
		||||
    ] ;
 | 
			
		||||
 | 
			
		||||
: py>py-quot ( py-function effect -- quot )
 | 
			
		||||
    in>> length swap '[ _ narray array>py-tuple _ call-or-eval ] ;
 | 
			
		||||
 | 
			
		||||
:: make-function ( basename format effect quot -- )
 | 
			
		||||
    basename format sprintf create-in
 | 
			
		||||
    current-module get basename getattr
 | 
			
		||||
    effect quot [ define-inline ] bi ; inline
 | 
			
		||||
 | 
			
		||||
:: add-function ( function effect -- )
 | 
			
		||||
    function "%s" effect [ factor>factor-quot ] make-function
 | 
			
		||||
    function "|%s" effect [ py>factor-quot ] make-function
 | 
			
		||||
    function "|%s|" effect in>> { "ret" } <effect> [ py>py-quot ] make-function
 | 
			
		||||
    function "%s|" effect in>> { "ret" } <effect> [ factor>py-quot ] make-function
 | 
			
		||||
    ; inline
 | 
			
		||||
 | 
			
		||||
: parse-python-word ( -- )
 | 
			
		||||
    scan-token dup ";" = [ drop ] [
 | 
			
		||||
        scan-effect add-function parse-python-word
 | 
			
		||||
    ] if ; inline recursive
 | 
			
		||||
 | 
			
		||||
SYNTAX: PY-FROM:
 | 
			
		||||
    scan-token import current-module set "=>" expect parse-python-word ; inline
 | 
			
		||||
		Loading…
	
		Reference in New Issue