racket/collects/web-server/lang/closure.ss
Eli Barzilay a70bf64fd9 Newlines at EOFs
svn: r15380
2009-07-04 02:28:31 +00:00

119 lines
4.8 KiB
Scheme

#lang scheme
(require syntax/free-vars
(for-template
scheme/base
scheme/serialize))
(define (define-closure! label fvars stx)
; Boxes
(define make-CLOSURE-box
(syntax-local-lift-expression
(quasisyntax/loc stx
(box (lambda (env) (error 'make-CLOSURE "Closure<~e> not initialized" '#,label))))))
(define CLOSURE-set-env!-box
(syntax-local-lift-expression
(quasisyntax/loc stx
(box (lambda (clsr new-env) (error 'CLOSURE-set-env! "Closure<~e> not initialized" '#,label))))))
(define CLOSURE-env-box
(syntax-local-lift-expression
(quasisyntax/loc stx
(box (lambda (clsr) (error 'CLOSURE-env "Closure<~e> not initialized" '#,label))))))
; Define the deserializer (req closure struct values under lambdas)
(define CLOSURE:deserialize-info-id
(syntax-local-lift-expression
(quasisyntax/loc stx
(make-deserialize-info
;; make-proc: value ... -> CLOSURE
(lambda args
(apply (#%plain-lambda #,fvars
((unbox #,make-CLOSURE-box) (#%plain-lambda () (values #,@fvars))))
args))
;; cycle-make-proc: -> (values CLOSURE (CLOSURE -> void))
(lambda ()
(let ([new-closure
((unbox #,make-CLOSURE-box)
(#%plain-lambda () (error 'deserialize "closure not initialized")))])
(values
new-closure
(#%plain-lambda (clsr)
((unbox #,CLOSURE-set-env!-box) new-closure ((unbox #,CLOSURE-env-box) clsr))))))))))
; Define the serializer (req closure struct values + deserializer identifier)
(define CLOSURE:serialize-info-id
(syntax-local-lift-expression
(quasisyntax/loc stx
(make-serialize-info
;; to-vector: CLOSURE -> vector
(#%plain-lambda (clsr)
(#%plain-app call-with-values
(#%plain-lambda () (((unbox #,CLOSURE-env-box) clsr)))
vector))
;; The serializer id: --------------------
(quote-syntax #,CLOSURE:deserialize-info-id)
;; can-cycle?
#t
;; Directory for last-ditch resolution --------------------
(or (current-load-relative-directory) (current-directory))))))
; Define the closure struct (req serialize info value)
(define-values
(make-CLOSURE-id CLOSURE?-id CLOSURE-env-id CLOSURE-set-env!-id)
(apply
values
(syntax-local-lift-values-expression
4
(quasisyntax/loc stx
(letrec-values ([(struct:CLOSURE make-CLOSURE CLOSURE? CLOSURE-ref CLOSURE-set!)
(make-struct-type
'#,label ;; the tag goes here
#f ; no super type
1
0 ; number of auto-fields
#f ; auto-v
; prop-vals:
(list (cons prop:serializable #,CLOSURE:serialize-info-id)
(cons prop:procedure
(#%plain-lambda (clsr . args)
(let-values ([#,fvars ((CLOSURE-ref clsr 0))])
(apply #,stx args)))))
#f ; inspector
;; the struct apply proc:
#f)]
[(CLOSURE-env)
(#%plain-lambda (clsr) (CLOSURE-ref clsr 0))]
[(CLOSURE-set-env!)
(#%plain-lambda (clsr new-env) (CLOSURE-set! clsr 0 new-env))])
(set-box! #,CLOSURE-env-box CLOSURE-env)
(set-box! #,CLOSURE-set-env!-box CLOSURE-set-env!)
(set-box! #,make-CLOSURE-box make-CLOSURE)
(values make-CLOSURE CLOSURE? CLOSURE-env CLOSURE-set-env!))))))
; Provide the deserializer (req deserializer identifier)
(syntax-local-lift-provide
(quasisyntax/loc stx
#,CLOSURE:deserialize-info-id))
(values make-CLOSURE-id CLOSURE?-id CLOSURE-env-id))
(define (make-closure stx)
(syntax-case stx ()
[(_ label lambda-stx)
(let*-values
([(lambda-fe-stx) (local-expand #'lambda-stx 'expression empty)]
[(fvars) (free-vars lambda-fe-stx)]
; Define the closure struct (req serialize info value)
[(make-CLOSURE-id CLOSURE?-id CLOSURE-env-id)
(define-closure! #'label fvars lambda-fe-stx)])
; Instantiate the closure
(quasisyntax/loc stx
(#,make-CLOSURE-id (#%plain-lambda () (values #,@fvars)))))]))
(provide
make-closure
define-closure!)