(define-module (language python compile) #:use-module (ice-9 match) #:use-module (ice-9 control) #:use-module (oop pf-objects) #:use-module (oop goops) #:use-module (language python exceptions) #:use-module (language python yield) #:use-module (language python for) #:use-module (language python try) #:use-module (ice-9 pretty-print) #:export (comp)) (define-syntax-rule (aif it p x y) (let ((it p)) (if it x y))) (define-syntax clear-warning-data (lambda (x) (set! (@@ (system base message) %dont-warn-list) '()) #f)) (define (dont-warn v) (set! (@@ (system base message) %dont-warn-list) (cons v (@@ (system base message) %dont-warn-list)))) (define-syntax call (syntax-rules () ((_ (f) . l) (f . l)))) (define (fold f init l) (if (pair? l) (fold f (f (car l) init) (cdr l)) init)) (define (pr . x) (define port (open-file "/home/stis/src/python-on-guile/log.txt" "a")) (with-output-to-port port (lambda () (pretty-print (syntax->datum x)))) (close port) (car (reverse x))) (define (pf x) (define port (open-file "/home/stis/src/python-on-guile/compile.log" "a")) (with-output-to-port port (lambda () (pretty-print (syntax->datum x)) x)) (close port) x) (define (C x) `(@@ (language python compile) ,x)) (define (Y x) `(@@ (language python yield) ,x)) (define (O x) `(@@ (oop pf-objects) ,x)) (define (G x) `(@ (guile) ,x)) (define (union as vs) (let lp ((as as) (vs vs)) (match as ((x . as) (if (member x vs) (lp as vs) (lp as (cons x vs)))) (() vs)))) (define (diff as vs) (let lp ((as as) (rs '())) (match as ((x . as) (if (member x vs) (lp as rs) (lp as (cons x rs)))) (() rs)))) (define (get-globals code) (let lp ((vs (glob code '())) (rs (scope code '()))) (match vs ((x . l) (if (member x rs) (lp l rs) (lp l (cons x rs)))) (() rs)))) (define (glob x vs) (match x ((#:global . l) (let lp ((l l) (vs vs)) (match l (((#:identifier v . _) . l) (let ((s (string->symbol v))) (if (member s vs) (lp l vs) (lp l (cons s vs))))) (() vs)))) ((x . y) (glob y (glob x vs))) (x vs))) (define (scope x vs) (match x ((#:def f . _) (union (list (exp '() f)) vs)) ((#:lambdef . _) vs) ((#:classdef f . _) (union (list (exp '() f)) vs)) ((#:global . _) vs) ((#:expr-stmt l (#:assign u)) (union (fold (lambda (x s) (match x ((#:test (#:power v2 v1 () . _) . _) (if v2 (union (union (list (exp '() v1)) (list (exp '() v2))) s) (union (list (exp '() v1)) s))) (_ s))) '() l) vs)) ((x . y) (scope y (scope x vs))) (_ vs))) (define (defs x vs) (match x ((#:def (#:identifier f . _) . _) (union (list (string->symbol f)) vs)) ((#:lambdef . _) vs) ((#:class . _) vs) ((#:global . _) vs) ((x . y) (defs y (defs x vs))) (_ vs))) (define (gen-yield f) (string->symbol (string-append (symbol->string f) ".yield"))) (define (g vs e) (lambda (x) (e vs x))) (define return (make-fluid 'error-return)) (define-syntax-rule (<< x y) (ash x y)) (define-syntax-rule (>> x y) (ash x (- y))) (define (make-set vs op x u) (define (tr-op op) (match op ("+=" '+) ("-=" '-) ("*=" '*) ("/=" '/) ("%=" 'modulo) ("&=" 'logand) ("|=" 'logior) ("^=" 'logxor) ("**=" 'expt) ("<<=" (C '<<)) (">>=" (C '>>)) ("//=" 'floor-quotient))) (match x ((#:test (#:power kind (#:identifier v . _) addings . _) . _) (let ((addings (map (lambda (x) (exp vs x)) addings))) (define q (lambda (x) `',x)) (if kind (let ((v (string->symbol v))) (if (null? addings) (if op `(set! ,v (,(tr-op op) ,v ,u)) `(set! ,v ,u)) (if op `(set! ,(exp vs kind) (,(O 'fset-x) ,v (list ,@(map q addings)) (,(tr-op op) (,(C 'ref-x) ,v ,@addings) ,u))) `(set! ,(exp vs kind) (,(O 'fset-x) ,v (list ,@(map q addings)) ,u))))) (let ((v (string->symbol v))) (if (null? addings) (if op `(set! ,v (,(tr-op op) (,(C 'ref-x) ,v ,@addings) ,u)) `(set! ,v ,u)) (let* ((rev (reverse addings)) (las (car rev)) (new (reverse (cdr rev)))) `(,(O 'set) ,(let lp ((v v) (new new)) (match new ((x . new) (lp `(,(O 'ref) ,v 'x) ',new)) (() v))) ',(exp vs las) ,(if op `(,(tr-op op) (,(C 'ref-x) ,v ,@addings) ,u) u)))))))))) (define is-class? (make-fluid #f)) (define (gen-yargs vs x) (match (pr 'yarg x) ((#:list args) (map (g vs exp) args)))) (define inhibit-finally #f) (define (exp vs x) (match (pr x) ((#:power _ (x) () . #f) (exp vs x)) ((#:power _ x () . #f) (exp vs x)) ;; Function calls (x1:x1.y.f(1) + x2:x2.y.f(2)) will do functional calls ((#:power #f vf trailer . **) (let () (define (pw x) (if ** `(expt ,x ,(exp vs **)) x)) (pw (let lp ((e (exp vs vf)) (trailer trailer)) (match trailer (() e) ((#f) (list e)) ((x . trailer) (match (pr x) ((#:identifier . _) (lp `(,(O 'ref) ,e ',(exp vs x) #f) trailer)) ((#:arglist args #f #f) (lp `(,e ,@(map (g vs exp) args)) trailer)) (_ (error "unhandled trailer"))))))))) ((#:identifier x . _) (string->symbol x)) ((#:string #f x) x) (((and x (or #:+ #:- #:* #:/)) . l) (cons (keyword->symbol x) (map (g vs exp) l))) ((#:% . l) (cons 'modulo (map (g vs exp) l))) ((#:// . l) (cons 'floor-quotient (map (g vs exp) l))) ((#:<< . l) (cons (C '<<) (map (g vs exp) l))) ((#:>> . l) (cons (C '>>) (map (g vs exp) l))) ((#:u~ x) (list 'lognot (exp vs x))) ((#:band . l) (cons 'logand (map (g vs exp) l))) ((#:bxor . l) (cons 'logxor (map (g vs exp) l))) ((#:bor . l) (cons 'logior (map (g vs exp) l))) ((#:not x) (list 'not (exp vs x))) ((#:or . x) (cons 'or (map (g vs exp) x))) ((#:and . x) (cons 'and (map (g vs exp) x))) ((#:test e1 #f) (exp vs e1)) ((#:test e1 e2 e3) (list 'if (exp vs e2) (exp vs e1) (exp vs e3))) ((#:if test a ((tests . as) ...) . else) `(,(G 'cond) (,(exp vs test) ,(exp vs a)) ,@(map (lambda (p a) (list (exp vs p) (exp vs a))) tests as) ,@(if else `((else ,(exp vs else))) '()))) ((#:suite . l) (cons 'begin (map (g vs exp) l))) (#:True #t) (#:False #f) (#:pass `(values)) ((#:while test code . #f) (let ((lp (gensym "lp"))) `(let ,lp () (if ,(exp vs test) (begin ,(exp vs code) (,lp)))))) ((#:classdef (#:identifier class . _) parents defs) (with-fluids ((is-class? #t)) (let () (define (filt l) (reverse (fold (lambda (x s) (match x ((or 'fast 'functional) s) (x (cons x s)))) '() l))) (define (is-functional l) (fold (lambda (x pred) (if pred pred (match x ('functional #t) (_ #f)))) #f l)) (define (is-fast l) (fold (lambda (x pred) (if pred pred (match x ('fast #t) (_ #f)))) #f l)) (let* ((class (string->symbol class)) (parents (match parents (() '()) (#f '()) ((#:arglist args . _) (map (g vs exp) args)))) (is-func (is-functional parents)) (is-fast (is-fast parents)) (kind (if is-func (if is-fast 'mk-pf-class 'mk-pyf-class) (if is-fast 'mk-p-class 'mk-py-class))) (parents (filt parents))) `(define ,class (,(O 'wrap) ,class (,(O kind) ,class ,(map (lambda (x) `(,(O 'get-class) ,x)) parents) #:const ,(match (exp vs defs) (('begin . l) l) ((('begin . l)) l) (l l)) #:dynamic ()))))))) ((#:import ((() nm) . #f)) `(use-modules (language python module ,(exp vs nm)))) (#:break (C 'break)) (#:continue (C 'continue)) ((#:for e in code . #f) (=> next) (match e (((#:power #f (#:identifier x . _) () . #f)) (match in (((#:test power . _)) (match power ((#:power #f (#:identifier "range" . _) ((#:arglist arglist . _)) . _) (match arglist ((arg) (let ((v (gensym "v")) (x (string->symbol x)) (lp (gensym "lp"))) `(let ((,v ,(exp vs arg))) (let ,lp ((,x 0)) (if (< ,x ,v) (begin ,(exp vs code) (,lp (+ ,x 1)))))))) ((arg1 arg2) (let ((v1 (gensym "va")) (v2 (gensym "vb")) (lp (gensym "lp"))) `(let ((,v1 ,(exp vs arg1)) (,v2 ,(exp vs arg2))) (let ,lp ((,x ,v1)) (if (< ,x ,v2) (begin ,(exp vs code) (,lp (+ ,x 1)))))))) ((arg1 arg2 arg3) (let ((v1 (gensym "va")) (v2 (gensym "vb")) (st (gensym "vs")) (lp (gensym "lp"))) `(let ((,v1 ,(exp vs arg1)) (,st ,(exp vs arg2)) (,v2 ,(exp vs arg3))) (if (> st 0) (let ,lp ((,x ,v1)) (if (< ,x ,v2) (begin ,(exp vs code) (,lp (+ ,x ,st))))) (if (< st 0) (let ,lp ((,x ,v1)) (if (> ,x ,v2) (begin ,(exp vs code) (,lp (+ ,x ,st))))) (error "range with step 0 not allowed")))))) (_ (next)))) (_ (next)))) (_ (next)))) (_ (next)))) ((#:for es in code . else) (let* ((es2 (map (g vs exp) es)) (vs2 (union es2 vs)) (code2 (exp vs2 code)) (p (is-ec #t code2 #t (list (C 'break) (C 'continue)))) (else2 (if else (exp vs2 else) #f)) (in2 (map (g vs exp) in))) (list (C 'for) es2 in2 code2 else2 p))) ((#:while test code else) (let ((lp (gensym "lp"))) `(let ,lp () (if test (begin ,(exp vs code) (,lp)) ,(exp vs else))))) ((#:try x (or #f ()) #f . fin) `(dynamic-wind (lambda () #f) (lambda () ,(exp vs x)) (lambda () (if (not ,(C 'inhibit-finally)) ,(exp vs fin))))) ((#:subexpr . l) (exp vs l)) ((#:try x exc else . fin) (define (guard x) (if fin `(dynamic-wind (lambda () #f) (lambda () ,x) (lambda () (if (not ,(C 'inhibit-finally)) ,(exp vs fin)))) x)) (define tag (gensym "tag")) (define o (gensym "o")) (define l (gensym "l")) (guard `(catch #t (lambda () ,(exp vs x)) (lambda (,tag ,o . ,l) ,(let lp ((it (if else (exp vs else) `(apply throw 'python ,tag ,o ,l))) (exc exc)) (match exc ((((test . #f) code) . exc) (lp `(if (,(O 'testex) ,tag ,o ,(exp vs test) ,l) ,(exp vs code) ,it) exc)) ((((test . as) code) . exc) (let ((a (exp vs as))) (lp `(if (,(O 'testex) ,tag ,o ,(exp vs test) ,l) (let ((,a ,o)) (,(O 'set) ,a '__excargs__ ,l) ,(exp vs code)) ,it) exc))) (() it))))))) ((#:raise #f . #f) `(throw 'python (,(O 'Exception)))) ((#:raise code . #f) (let ((c (gensym "c"))) `(throw 'python (let ((,c ,(exp vs code))) (if (,(O 'pyclass?) ,c) (,c) ,c))))) ((#:raise code . from) (let ((o (gensym "o")) (c (gensym "c"))) `(throw 'python (let ((,c ,(exp vs code))) (let ((,o (if (,(O 'pyclass?) ,c) (,c) ,c))) (,(O 'set) ,o '__cause__ ,(exp vs from)) ,o))))) ((#:yield args) (let ((f (gensym "f"))) `(begin (fluid-set! ,(Y 'in-yield) #t) (let ((,f (scm.yield ,@(gen-yargs vs args)))) (,f))))) ((#:yield f args) (let ((f (gen-yield (exp vs f))) (g (gensym "f"))) `(begin (set! ,(C 'inhibit-finally) #t) (let ((,g (,f ,@(gen-yargs vs args)))) (,g))))) ((#:def f (#:types-args-list args #f #f) #f code) (let* ((c? (fluid-ref is-class?)) (f (exp vs f)) (y? (is-yield f #f code)) (r (gensym "return")) (as (map (lambda (x) (match x ((((#:identifier x . _) . #f) #f) (string->symbol x)))) args)) (ab (gensym "ab")) (vs (union as vs)) (ns (scope code vs)) (df (defs code '())) (ex (gensym "ex")) (y 'scm.yield) (y.f (gen-yield f)) (ls (diff (diff ns vs) df))) (define (mk code) `(let-syntax ((,y (syntax-rules () ((_ . args) (abort-to-prompt ,ab . args)))) (,y.f (syntax-rules () ((_ . args) (abort-to-prompt ,ab . args))))) ,code)) (with-fluids ((is-class? #f)) (if c? (if y? `(define ,f (,(C 'def-wrap) ,y? ,f ,ab (lambda (,@as) (,(C 'with-return) ,r ,(mk `(let ,(map (lambda (x) (list x #f)) ls) ,(with-fluids ((return r)) (exp ns code)))))))) `(define ,f (letrec ((,f (case-lambda ((,ex ,@as) (,f ,@as)) ((,@as) (,(C 'with-return) ,r ,(mk `(let ,(map (lambda (x) (list x #f)) ls) ,(with-fluids ((return r)) (exp ns code))))))))) ,f))) (if y? `(define ,f (,(C 'def-wrap) ,y? ,f ,ab (lambda (,@as) (,(C 'with-return) ,r (let ,(map (lambda (x) (list x #f)) ls) ,(with-fluids ((return r)) (mk (exp ns code)))))))) `(define ,f (lambda (,@as) (,(C 'with-return) ,r (let ,(map (lambda (x) (list x #f)) ls) ,(with-fluids ((return r)) (exp ns code))))))))))) ((#:global . _) '(values)) ((#:lambdef v e) (list `lambda v (exp vs e))) ((#:stmt l) (if (> (length l) 1) (cons 'values (map (g vs exp) l)) (exp vs (car l)))) ((#:expr-stmt (l) (#:assign)) (exp vs l)) ((#:expr-stmt l type) (=> fail) (call-with-values (lambda () (match type ((#:assign u) (values #f u)) ((#:augassign op u) (values op u)) (_ (fail)))) (lambda (op u) (cond ((= (length l) (length u)) (if (= (length l) 1) (make-set vs op (car l) (exp vs (car u))) (cons 'begin (map (lambda (l u) (make-set vs op l u)) l (map (g vs exp) u))))) ((and (= (length u) 1) (not op)) (let ((vars (map (lambda (x) (gensym "v")) l))) `(call-with-values (lambda () (exp vs (car u))) (lambda vars ,@(map (lambda (l v) (make-set vs op l v)) l vars))))))))) ((#:return . x) `(,(fluid-ref return) ,@(map (g vs exp) x))) ((#:expr-stmt ((#:test (#:power #f (#:identifier v . _) () . #f) #f)) (#:assign (l))) (let ((s (string->symbol v))) `(set! ,s ,(exp vs l)))) ((#:comp x #f) (exp vs x)) ((#:comp x (op . y)) (define (tr op x y) (match op ((or "<" ">" "<=" ">=") (list (G (string->symbol op)) x y)) ("!=" (list 'not (list 'equal? x y))) ("==" (list 'equal? x y)) ("is" (list 'eq? x y)) ("isnot" (list 'not (list 'eq? x y))) ("in" (list 'member x y)) ("notin" (list 'not (list 'member x y))) ("<>" (list 'not (list 'equal? x y))))) (tr op (exp vs x) (exp vs y))) (x x))) (define (comp x) (define start (match (pr 'start x) (((#:stmt ((#:expr-stmt ((#:test (#:power #f (#:identifier "module" . _) ((#:arglist arglist #f #f)) . #f) #f)) (#:assign)))) . _) (let () (define args (map (lambda (x) (exp '() x)) arglist)) `((,(G 'define-module) (language python module ,@args) #:use-module (language python module python))))) (x '()))) (if (pair? start) (set! x (cdr x))) (let ((globs (get-globals x))) `(begin ,@start ,(C 'clear-warning-data) (set! (@@ (system base message) %dont-warn-list) '()) ,@(map (lambda (s) `(,(C 'var) ,s)) globs) ,@(map (g globs exp) x)))) (define-syntax-parameter break (lambda (x) #'(values))) (define-syntax-parameter continue (lambda (x) (error "continue must be bound"))) (define (is-yield f p x) (match x ((#:def nm args _ code) (is-yield f #t code)) ((#:yield x _) (eq? f (exp '() x))) ((#:yield _) (not p)) ((a . l) (or (is-yield f p a) (is-yield f p l))) (_ #f))) (define-syntax-rule (with-sp ((x v) ...) code ...) (syntax-parameterize ((x (lambda (y) #'v)) ...) code ...)) (define (is-ec ret x tail tags) (syntax-case (pr 'is-ec x) (begin let if define @@) ((begin a ... b) #t (or (or-map (lambda (x) (is-ec ret x #f tags)) #'(a ...)) (is-ec ret #'b tail tags))) ((let lp ((y x) ...) a ... b) (symbol? (syntax->datum #'lp)) (or (or-map (lambda (x) (is-ec ret x #f tags)) #'(x ...)) (or-map (lambda (x) (is-ec ret x #f tags)) #'(a ...)) (is-ec ret #'b tail tags))) ((let ((y x) ...) a ... b) #t (or (or-map (lambda (x) (is-ec ret x #f tags)) #'(x ...)) (or-map (lambda (x) (is-ec ret x #f tags)) #'(a ...)) (is-ec ret #'b tail tags))) ((if p a b) #t (or (is-ec ret #'p #f tags) (is-ec ret #'a tail tags) (is-ec ret #'b tail tags))) ((define . _) #t #f) ((if p a) #t (or (is-ec ret #'p #f tags) (is-ec ret #'a tail tags))) ((@@ _ _) #t (if (member (pr (syntax->datum x)) tags) #t #f)) ((a ...) #t (or-map (lambda (x) (is-ec ret x #f tags)) #'(a ...))) (x #t #f))) (define-syntax with-return (lambda (x) (define (analyze ret x) (syntax-case x (begin let if) ((begin a ... b) #`(begin a ... #,(analyze ret #'b))) ((let lp v a ... b) (symbol? (syntax->datum #'lp)) #`(let lp v a ... #,(analyze ret #'b))) ((let v a ... b) #`(let v a ... #,(analyze ret #'b))) ((if p a b) #`(if p #,(analyze ret #'a) #,(analyze ret #'b))) ((if p a) #`(if p #,(analyze ret #'a))) ((return a b ...) (equal? (syntax->datum #'return) (syntax->datum ret)) (if (eq? #'(b ...) '()) #'a #`(values a b ...))) (x #'x))) (define (is-ec ret x tail) (syntax-case x (begin let if define @@) ((begin a ... b) #t (or (or-map (lambda (x) (is-ec ret x #f)) #'(a ...)) (is-ec ret #'b tail))) ((let lp ((y x) ...) a ... b) (symbol? (syntax->datum #'lp)) (or (or-map (lambda (x) (is-ec ret x #f)) #'(x ...)) (or-map (lambda (x) (is-ec ret x #f)) #'(a ...)) (is-ec ret #'b tail))) ((let ((y x) ...) a ... b) #t (or (or-map (lambda (x) (is-ec ret x #f)) #'(x ...)) (or-map (lambda (x) (is-ec ret x #f)) #'(a ...)) (is-ec ret #'b tail))) ((define . _) #t #f) ((if p a b) #t (or (is-ec ret #'p #f) (is-ec ret #'a tail) (is-ec ret #'b tail))) ((if p a) #t (or (is-ec ret #'p #f) (is-ec ret #'a tail))) ((return a b ...) (equal? (syntax->datum #'return) (syntax->datum ret)) (not tail)) ((a ...) #t (or-map (lambda (x) (is-ec ret x #f)) #'(a ...))) (x #t #f))) (syntax-case x () ((_ ret l) (let ((code (analyze #'ret #'l))) (if (is-ec #'ret #'l #t) #`(let/ec ret #,code) code)))))) (define-syntax var (lambda (x) (syntax-case x () ((_ v) (begin (dont-warn (syntax->datum #'v)) #'(if (module-defined? (current-module) 'v) (values) (define! 'v #f))))))) (define-inlinable (non? x) (eq? x #:nil)) (define-syntax for (syntax-rules () ((_ (x) (a) code #f #f) (if (pair? a) (let lp ((l a)) (if (pair? l) (let ((x (car l))) (with-sp ((continue (lp (cdr l))) (break (values))) code (lp (cdr l)))))) (for/adv1 (x) (a) code #f #f))) ((_ (x) (a) code #f #t) (if (pair? a) (let/ec break-ret (let lp ((l a)) (if (pair? l) (begin (let/ec continue-ret (let ((x (car l))) (with-sp ((continue (continue-ret)) (break (break-ret))) code))) (lp (cdr l)))))) (for/adv1 (x) (a) code #f #t))) ((_ (x) (a) code next #f) (if (pair? a) (let/ec break-ret (let ((x (let lp ((l a) (old #f)) (if (pair? l) (let ((x (car l))) (let/ec continue-ret (with-sp ((continue (continue-ret)) (break (break-ret))) code)) (lp (cdr l))) old)))) next)) (for/adv1 (x) (a) code next #f))) ((_ x a code next p) (for/adv1 x a code next p)))) (define-syntax for/adv1 (lambda (x) (syntax-case x () ((_ (x ...) (in ...) code #f #f) (with-syntax (((inv ...) (generate-temporaries #'(in ...)))) #'(let ((inv (wrap-in in)) ...) (catch StopIteration (lambda () (let lp () (call-with-values (lambda () (values (next inv) ...)) (lambda (x ...) (with-sp ((break (values)) (continue (values))) code (lp)))))) (lambda z (values)))))) ((_ (x ...) (in ...) code #f #t) (with-syntax (((inv ...) (generate-temporaries #'(in ...)))) #'(let ((inv (wrap-in in)) ...) (let lp () (let/ec break-ret (catch StopIteration (lambda () (call-with-values (lambda () (values (next inv) ...)) (lambda (x ...) (let/ec continue-ret (with-sp ((break (break-ret)) (continue (continue-ret))) code)) (lp)))) (lambda z (values)))))))) ((_ (x ...) in code else #f) #'(for-adv (x ...) in code else #f)) ((_ (x ...) in code else #t) #'(for-adv (x ...) in code else #t))))) (define-syntax for-adv (lambda (x) (define (gen x y) (if (= (length (syntax->datum x)) (= (length (syntax->datum y)))) (syntax-case x () ((x ...) #'(values (next x) ...))) (syntax-case x () ((x) #'(next x))))) (syntax-case x () ((_ (x ...) (in ...) code else p) (with-syntax (((inv ...) (generate-temporaries #'(in ...)))) (with-syntax ((get (gen #'(inv ...) #'(x ...))) ((xx ...) (generate-temporaries #'(x ...)))) (if (syntax->datum #'p) #'(let ((inv (wrap-in in)) ...) (let/ec break-ret (let ((x #f) ...) (catch StopIteration (lambda () (let lp () (call-with-values (lambda () get) (lambda (xx ...) (set! x xx) ... (let/ec continue-ret (with-sp ((break (break-ret)) (continue (continue-ret))) code)) (lp))))) (lambda q else))))) #'(let ((inv (wrap-in in)) ...) (let ((x #f) ...) (let/ec break-ret (catch StopIteration (lambda () (let lp () (call-with-values (lambda () get) (lambda (xx ...) (set! x xx) ... (with-sp ((break (break-ret)) (continue (values))) code) (lp))))) (lambda e else)))))))))))) (define-syntax def-wrap (lambda (x) (syntax-case x () ((_ #f f ab x) (pr 'def-wrap #'f 'false) #'x) ((_ #t f ab code) (pr 'def-wrap #'f 'true) #'(lambda x (define obj (make )) (define ab (make-prompt-tag)) (slot-set! obj 'k #f) (slot-set! obj 'closed #f) (slot-set! obj 's (lambda () (call-with-prompt ab (lambda () (let/ec return (apply code x)) (slot-set! obj 'closed #t) (throw StopIteration)) (letrec ((lam (lambda (k . l) (fluid-set! in-yield #f) (slot-set! obj 'k (lambda (a) (call-with-prompt ab (lambda () (k a)) lam))) (apply values l)))) lam)))) obj))))) (define-syntax ref-x (syntax-rules () ((_ v) v) ((_ v x . l) (ref-x (ref v 'x) . l))))