summaryrefslogtreecommitdiff
path: root/modules/language/python/#python.scm#
diff options
context:
space:
mode:
Diffstat (limited to 'modules/language/python/#python.scm#')
-rw-r--r--modules/language/python/#python.scm#246
1 files changed, 246 insertions, 0 deletions
diff --git a/modules/language/python/#python.scm# b/modules/language/python/#python.scm#
new file mode 100644
index 0000000..cb36775
--- /dev/null
+++ b/modules/language/python/#python.scm#
@@ -0,0 +1,246 @@
+(define-module (language python python)
+ #:use-module (language python parser)
+ #:use-module (language python expr)
+ #:use-module (ice-9 match)
+ #:export (compile-python-string compile-python-file))
+
+;;; VARIABLES ----------------------------------------------------------------
+(define (find-global-variables vars tree)
+ (define (for-each* f l)
+ (match l
+ ((x . l)
+ (f x)
+ (for-each* f l))
+ (x
+ (f x))))
+
+ (define (local tree)
+ (match tree
+ ((#:global l)
+ (for-each*
+ (lambda (x) (hash-set! vars x #t)) l))
+ ((x . l)
+ (for-each* local tree))
+ (_
+ #t)))
+
+ (define (collect tree)
+ (match tree
+ ((#:lambdef . _)
+ #t)
+ ((#:identifier . l)
+ (hash-set! vars tree #t))
+ ((_ . _)
+ (for-each* collect tree))
+ (_
+ #t)))
+
+ (let lp ((tree tree))
+ (match tree
+ ((#:def . l)
+ (for-each* local l))
+ ((#:lambdef . l)
+ (for-each* local l))
+ ((#:class . l)
+ (for-each* local l))
+ ((#:expr-stmt
+ a (#:assign x ... e))
+ (collect a)
+ (collect x))
+ ((x . l)
+ (for-each* lp tree))
+ (_
+ #t))))
+;; COMPILATION
+
+(define (expr stx out tree)
+ (define (expr-lhs tree)
+ (match tree
+ ((#:test (#:power (#:identifier v . _)))
+ (datum->syntax stx (string->symbol v)))))
+
+
+ (define (expr-rhs tree)
+ (define (comp-tr op)
+ (match op
+ ("notin" #'py-notin)
+ ("isnot" #'py-isnot)
+ ("==" #'py_==)
+ (">=" #'py_>=)
+ ("<=" #'py_<=)
+ ("<>" #'py_<>)
+ ("!=" #'py_!=)
+ ("in" #'py_in)
+ ("is" #'py_is)
+ ("<" #'py_< )
+ (">" #'py_> )))
+
+ (let lp ((tree tree))
+ (match tree
+ ((#:test x #f)
+ (lp x))
+ ((#:test x (a b))
+ #`(if #,(py-true? (lp a)) #,(lp x) #,(lp b)))
+ ((#:or x . y)
+ #`(py-or #,(lp x) #,@(map lp y)))
+ ((#:and x y)
+ #`(py-and #,(lp x) #,@(map lp y)))
+ ((#:not x)
+ #`(py-not #,(lp x)))
+ ((#:comp x)
+ (lp x))
+ ((#:comp x (op . y) . l)
+ #'(#,(comp-tr op) #,(lp x) #,(lp (cons* #:comp y l))))
+ ((#:bor x y)
+ #`(py-bor #,(lp x) #,@(map lp y)))
+ ((#:bxor x y)
+ #`(py-bxor #,(lp x) #,@(map lp y)))
+ ((#:xand x y)
+ #`(py-band #,(lp x) #,@(map lp y)))
+ ((#:<< x y)
+ #`(py-<< #,(lp x) #,@(map lp y)))
+ ((#:>> x y)
+ #`(py->> #,(lp x) #,@(map lp y)))
+ ((#:+ x y)
+ #`(py-+ #,(lp x) #,@(map lp y)))
+ ((#:- x y)
+ #`(py-- #,(lp x) #,@(map lp y)))
+ ((#:* x y)
+ #`(py-* #,(lp x) #,@(map lp y)))
+ ((#:/ x y)
+ #`(py-/ #,(lp x) #,@(map lp y)))
+ ((#:// x y)
+ #`(py-// #,(lp x) #,@(map lp y)))
+ ((#:% x y)
+ #`(py-% #,(lp x) #,@(map lp y)))
+ ((#:u+ x)
+ #`(py-u+ #,(lp x)))
+ ((#:u- x)
+ #`(py-u- #,(lp x)))
+ ((#:u~ x)
+ #`(py-u~ #,(lp x)))
+ ((#:power x trailer . #f)
+ (compile-trailer trailer (lp x)))
+ ((#:power x trailer . l)
+ #'(py-power ,#(compile-trailer trailer (lp x)) #,(lp l)))
+ ((#:identifier x . _)
+ (datum->syntax stx (string->symbol x)))
+ ((not (_ . _))
+ tree))))
+
+
+
+ (lambda (tree)
+ (match tree
+ ((test1 (#:assign))
+ (expr-rhs test1))
+ ((test1 (#:assign tests ... last))
+ (with-syntax (((rhs ...) (map expr-rhs last))
+ ((lhs1 ...) (map expr-lhs test1))
+ (((lhs ...) ...) (reverse (map (lambda (l)
+ (map expr-lhs l))
+ tests))))
+ (with-syntax (((v ...) (generate-temporaries #'(lhs1 ...))))
+ (out #'(call-with-values (lambda () (values rhs ...))
+ (lambda (v ...)
+ (begin
+ (set! lhs v) ...)
+ ...
+ (set! lhs1 v) ...)))))))))
+
+
+(define (compile-outer state out tree)
+ (define (compile-stmt state tree)
+ (match tree
+ ((#:expr-stmt l)
+ (compile-expr l))
+
+ ((#:del l)
+ (compile-del l))
+
+ (#:pass
+ (out #'(if #f #f)))
+
+ (#:break
+ (break out))
+
+ (#:continue
+ (continue out))
+
+ ((#:return . l)
+ (compile-return state l))
+
+ ((#:raise . l)
+ (compile-raise state l))
+
+ ((#:import l)
+ (compile-import state l))
+
+ ((#:global . _)
+ #t)
+
+ ((#:nonlocal . _)
+ #t)
+
+ ((#:assert . l)
+ (compile-assert state l))))
+
+ (match tree
+ ((#:stmt x)
+ (for-each* compile-stmt tree))
+ ((#:if . l)
+ (compile-if state l))
+ ((#:while . l)
+ (compile-while state l))
+ ((#:for . l)
+ (compile-for state l))
+ ((#:try . l)
+ (compile-try state l))
+ ((#:with . l)
+ (compile-with state l))
+ ((#:def . l)
+ (compile-def state l))
+ ((#:decorated . l)
+ (compile-decorated state l))))
+
+
+(define (compile-python0 stx tree output)
+ (define global-variables (make-hash-table))
+
+ (find-global-variables global-variables tree)
+ (set! all-variables
+ (hash-fold
+ (lambda (k v e)
+ (match k
+ ((_ v . _)
+ (cons (datum->syntax stx (string->symbol v)) e))))
+ '() global-variables))
+ (set! all-globals
+ (hash-fold
+ (lambda (k v e)
+ (match k
+ ((_ v)
+ (cons (datum->syntax stx (string->symbol v)) e))))
+ '() global-variables))
+
+ (output (with-syntax (((v ...) all-variables))
+ #'(begin (define v (if #f #f)) ...)))
+
+ (output (with-syntax (((v ...) all-globals))
+ #'(export v ...)))
+
+ (output #`(begin #,@(compile-outer))))
+
+
+(define (compile-python1 stx tree)
+ (let ((out '()))
+ (define (out x) (set! out (cons x out)))
+ (compile-python0 stx tree out)
+ (cons* #'begin (reverse out))))
+
+(define-syntax compile-python-string
+ (lambda (x)
+ (syntax-case x ()
+ ((_ y)
+ (if (string? (syntax->datum #'y))
+ (compile-python1 x (python-parser