]> gitweb.factorcode.org Git - factor.git/commitdiff
python.syntax: vocab that makes python functions work like factor words
authorBjörn Lindqvist <bjourne@gmail.com>
Tue, 28 Jan 2014 18:19:57 +0000 (19:19 +0100)
committerJohn Benediktsson <mrjbq7@gmail.com>
Tue, 4 Mar 2014 17:23:04 +0000 (09:23 -0800)
extra/python/ffi/ffi.factor
extra/python/python-tests.factor
extra/python/python.factor
extra/python/stdlib/builtin/builtin.factor [deleted file]
extra/python/stdlib/sys/sys.factor [deleted file]
extra/python/syntax/syntax-tests.factor [new file with mode: 0644]
extra/python/syntax/syntax.factor [new file with mode: 0644]

index a9c394a6a790e77a355d8d595cf5cec1ac55443f..b12fa5c2bf8431a6f7094bad8623e5b39e3c9af0 100644 (file)
@@ -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 ) ;
index 7bf73f413e4aa2d7d99aaea98e259f2f340011d4..7351a6f3f22e9b454c38a6f3b178bd96611da4a0 100644 (file)
@@ -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
index c5467d415d9cc8c65df8b8476b080ed7075e2874..54016efcef1281cb3505cea5ddc6f5a8d1885541 100644 (file)
@@ -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 )
diff --git a/extra/python/stdlib/builtin/builtin.factor b/extra/python/stdlib/builtin/builtin.factor
deleted file mode 100644 (file)
index cc070aa..0000000
+++ /dev/null
@@ -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 ;
diff --git a/extra/python/stdlib/sys/sys.factor b/extra/python/stdlib/sys/sys.factor
deleted file mode 100644 (file)
index 14657e9..0000000
+++ /dev/null
@@ -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 ;
diff --git a/extra/python/syntax/syntax-tests.factor b/extra/python/syntax/syntax-tests.factor
new file mode 100644 (file)
index 0000000..64b7d2f
--- /dev/null
@@ -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
diff --git a/extra/python/syntax/syntax.factor b/extra/python/syntax/syntax.factor
new file mode 100644 (file)
index 0000000..1068904
--- /dev/null
@@ -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