80 lines
3.1 KiB
Racket
80 lines
3.1 KiB
Racket
#lang racket/base
|
|
|
|
(require (for-syntax racket/base
|
|
syntax/kerncase))
|
|
|
|
(provide (except-out (all-from-out racket/base) #%module-begin)
|
|
(rename-out [*module-begin #%module-begin]))
|
|
|
|
;; Module wrapper ----------------------------------------
|
|
|
|
(define-syntax (*module-begin stx)
|
|
(syntax-case stx ()
|
|
[(_ id post-process exprs . body)
|
|
#'(#%module-begin
|
|
(doc-begin id post-process exprs . body))]))
|
|
|
|
(define-syntax (doc-begin stx)
|
|
(syntax-case stx ()
|
|
[(_ m-id post-process (expr ...))
|
|
#`(begin
|
|
(define m-id (post-process (list . #,(reverse (syntax->list #'(expr ...))))))
|
|
(provide m-id))]
|
|
[(_ m-id post-process exprs . body)
|
|
;; `body' probably starts with lots of string constants; it's
|
|
;; slow to trampoline on every string, so do them in a batch
|
|
;; here:
|
|
(let loop ([body #'body]
|
|
[accum null])
|
|
(syntax-case body ()
|
|
[(s . rest)
|
|
(string? (syntax-e #'s))
|
|
(loop #'rest (cons #'s accum))]
|
|
[()
|
|
(with-syntax ([(accum ...) accum])
|
|
#`(doc-begin m-id post-process (accum ... . exprs)))]
|
|
[(body1 . body)
|
|
(with-syntax ([exprs (append accum #'exprs)])
|
|
(let ([expanded (local-expand
|
|
#'body1 'module
|
|
(append (kernel-form-identifier-list)
|
|
(syntax->list #'(provide
|
|
require
|
|
#%provide
|
|
#%require))))])
|
|
(syntax-case expanded (begin)
|
|
[(begin body1 ...)
|
|
#`(doc-begin m-id post-process exprs body1 ... . body)]
|
|
[(id . rest)
|
|
(and (identifier? #'id)
|
|
(ormap (lambda (kw) (free-identifier=? #'id kw))
|
|
(syntax->list #'(require
|
|
provide
|
|
define-values
|
|
define-syntaxes
|
|
begin-for-syntax
|
|
module
|
|
module*
|
|
#%require
|
|
#%provide))))
|
|
#`(begin #,expanded (doc-begin m-id post-process exprs . body))]
|
|
[_else
|
|
#`(doc-begin m-id post-process
|
|
((pre-part #,expanded body1) . exprs)
|
|
. body)])))]))]))
|
|
|
|
(define-syntax (pre-part stx)
|
|
(syntax-case stx ()
|
|
[(_ s e)
|
|
(if (string? (syntax-e #'s))
|
|
#'s
|
|
(with-syntax ([src (syntax-source #'e)]
|
|
[line (syntax-line #'e)]
|
|
[col (syntax-column #'e)]
|
|
[pos (syntax-position #'e)]
|
|
[span (syntax-column #'e)])
|
|
#'(check-pre-part e (vector 'src 'line 'col 'pos 'span))))]))
|
|
|
|
(define (check-pre-part v s)
|
|
v)
|