#lang racket/base (require (for-template racket/base) syntax/kerncase racket/contract web-server/lang/closure (for-template web-server/lang/serial-lambda) "util.rkt") (provide/contract [defun (syntax? . -> . syntax?)]) ; make-new-clouse-label : (syntax -> syntax) syntax -> syntax (define (make-new-closure-label labeling stx) (labeling stx)) ; defun : syntax[1] -> (values syntax?[2] (listof syntax?)[3]) ; defunctionalizes the first syntax, returning the second and the lifted lambdas [3] (define (defun stx) (recertify stx (kernel-syntax-case stx (transformer?) [(begin be ...) (let-values ([(nbes) (defun* (syntax->list #'(be ...)))]) (quasisyntax/loc stx (begin #,@nbes)))] [(begin0 be ...) (let-values ([(nbes) (defun* (syntax->list #'(be ...)))]) (quasisyntax/loc stx (begin0 #,@nbes)))] [(set! v ve) (let-values ([(nve) (defun #'ve)]) (quasisyntax/loc stx (set! v #,nve)))] [(let-values ([(v ...) ve] ...) be ...) (let-values ([(nves) (defun* (syntax->list #'(ve ...)))] [(nbes) (defun* (syntax->list #'(be ...)))]) (with-syntax ([(nve ...) nves] [(nbe ...) nbes]) (syntax/loc stx (let-values ([(v ...) nve] ...) nbe ...))))] [(letrec-values ([(v ...) ve] ...) be ...) (let-values ([(nves) (defun* (syntax->list #'(ve ...)))] [(nbes) (defun* (syntax->list #'(be ...)))]) (with-syntax ([(nve ...) nves] [(nbe ...) nbes]) (syntax/loc stx (letrec-values ([(v ...) nve] ...) nbe ...))))] [(#%plain-lambda formals be ...) (let-values ([(nbes) (defun* (syntax->list #'(be ...)))]) (with-syntax ([(nbe ...) nbes]) (syntax/loc stx (serial-lambda formals nbe ...)) #; (make-closure (quasisyntax/loc stx (_ #,(make-new-closure-label (current-code-labeling) stx) (#%plain-lambda formals nbe ...))))))] [(case-lambda [formals be ...] ...) (let-values ([(nbes) (defun** (syntax->list #'((be ...) ...)))]) (with-syntax ([((nbe ...) ...) nbes]) (syntax/loc stx (serial-case-lambda [formals nbe ...] ...)) #; (make-closure (quasisyntax/loc stx (_ #,(make-new-closure-label (current-code-labeling) stx) (case-lambda [formals nbe ...] ...))))))] [(if te ce ae) (let-values ([(es) (defun* (syntax->list #'(te ce ae)))]) (quasisyntax/loc stx (if #,@es)))] [(quote datum) stx] [(quote-syntax datum) stx] [(with-continuation-mark ke me be) (let-values ([(es) (defun* (list #'ke #'me #'be))]) (quasisyntax/loc stx (with-continuation-mark #,@es)))] [(#%plain-app e ...) (let-values ([(es) (defun* (syntax->list #'(e ...)))]) (quasisyntax/loc stx (#%plain-app #,@es)))] [(#%top . v) stx] [(#%variable-reference . v) stx] [id (identifier? #'id) stx] [(#%expression d) (let-values ([(nd) (defun #'d)]) (quasisyntax/loc stx (#%expression #,nd)))] [_ (raise-syntax-error 'defun "Dropped through:" stx)]))) ; lift defun to list of syntaxes (define (lift-defun defun) (lambda (stxs) (map defun stxs))) (define defun* (lift-defun defun)) (define defun** (lift-defun (lambda (stx) (defun* (syntax->list stx)))))