#lang scheme/base
(provide
let-ns-tx define-ns-tx
redefine!-ns-tx
definitions-ns-tx
parameterize-words-ns-tx
parameterize/super-words-ns-tx
ns-prefixed
make-ns-ref make-ns-bind
name->identifier
)
(require
(lib "pretty.ss")
scheme/stxparam
syntax/modcode
syntax/modresolve
scheme/pretty
mzlib/pregexp
"../tools-tx.ss"
(for-template
"../tools.ss"
"rep.ss" scheme/base
)
)
(define (make-ns-ref ns)
(lambda (stx)
(syntax-case stx ()
((_ id)
(ns-prefixed ns #'id)))))
(define (make-ns-bind let ns)
(lambda (stx)
(syntax-case stx ()
((_ ((name/names expr) ...) body ...)
#`(#,let
#,(map
(lambda (n/ns e)
#`(#,(syntax-case n/ns ()
((name ...)
(map (lambda (n) (ns-prefixed ns n))
(syntax->list #'(name ...))))
(name
(ns-prefixed ns #'name)))
#,e))
(syntax->list #'(name/names ...))
(syntax->list #'(expr ...)))
body ...)))))
(define ns-separator "/")
(define (ns->prefix-string ns-lst)
(apply string-append
(map (lambda (x) (format "~a~a" x ns-separator))
ns-lst)))
(define (ns->prefix ns-stx)
(->syntax ns-stx
(string->symbol
(ns->prefix-string
(->datum ns-stx)))))
(define (name->identifier stx)
(let ((name (syntax->datum stx)))
(cond
((symbol? name) stx)
((string? name) (datum->syntax stx (string->symbol name)))
(else #f))))
(define (ns-prefixed ns name) (prefix (ns->prefix ns)
(name->identifier name)))
(define (let-ns-tx stx)
(syntax-case stx ()
((let ns . args)
#`(let-syntax
((let/ns (make-ns-bind #'let #'ns)))
(let/ns . args)))))
(define (define-ns-tx stx)
(syntax-case stx ()
((define ns name val)
(let ((mapped (ns-prefixed #'ns #'name)))
#`(define #,mapped val)))))
(define (redefine!-ns-tx stx)
(syntax-case stx ()
((define ns name val)
(let ((id (ns-prefixed #'ns #'name)))
(if (identifier-binding id)
(let ((super
(ns-prefixed
#'ns (datum->syntax #'name 'super))))
#`(letrec ((#,super val))
(log: "~a ~a\n" 'ns 'name)
(word-swap! #,super #,id)))
#`(define #,id val))))))
(define (definitions-ns-tx stx)
(syntax-case stx ()
((define-ns ns (name val) ...)
#`(begin (define-ns ns name val) ...))))
(define (suffix-temp stx-lst suffix)
(generate-temporaries
(map (lambda (id)
(format "~a~a" id suffix))
(syntax->datum stx-lst))))
(define (parameterize-words-ns-tx stx)
(syntax-case stx ()
((word->param ns ((name expr) ...) body ...)
#`(let-syntax
((id (make-ns-ref #'ns)))
(parameterize
(((word->param (id name)) expr) ...)
body ...)))))
(define (parameterize/super-words-ns-tx stx)
(syntax-case stx ()
((_ _ () body ...) #`(let () body ...)) ((word->param ns ((name expr) ...) body ...)
(syntax-case
(list
(ns-prefixed #'ns
(datum->syntax
(stx-car #'(name ...))
'super))
(suffix-temp #'(name ...) "-param-") (suffix-temp #'(name ...) "-value-")) ()
((super (pname ...) (pvalue ...))
#`(let-syntax
((_ns (make-ns-ref #'ns)))
(let ((pname (word->param (_ns name))) ...)
(let ((pvalue (pname)) ...)
(parameterize
((pname (let ((super pvalue)) expr)) ...)
body ...)))))))))