mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-03 13:20:26 +02:00
rewrite define-module as a syntax-case macro
* module/ice-9/boot-9.scm (define-module): Rewrite as a syntax-case macro, so that the expansion has proper module hygiene. Otherwise process-define-module isn't properly resolved against the root module -- a bytecode file that starts with a define-module would just try to look up process-define-module from the current module. (compile-define-module-args): Remove. Internal, and no one else used it.
This commit is contained in:
parent
a40e1c9078
commit
074e036ee2
1 changed files with 71 additions and 42 deletions
|
@ -3283,49 +3283,78 @@ module '(ice-9 q) '(make-q q-length))}."
|
||||||
(define (keyword-like-symbol->keyword sym)
|
(define (keyword-like-symbol->keyword sym)
|
||||||
(symbol->keyword (string->symbol (substring (symbol->string sym) 1))))
|
(symbol->keyword (string->symbol (substring (symbol->string sym) 1))))
|
||||||
|
|
||||||
(define (compile-define-module-args args)
|
;; FIXME: we really need to clean up the guts of the module system.
|
||||||
;; Just quote everything except #:use-module and #:use-syntax. We
|
;; We can compile to something better than process-define-module.
|
||||||
;; need to know about all arguments regardless since we want to turn
|
(define-syntax define-module
|
||||||
;; symbols that look like keywords into real keywords, and the
|
(lambda (x)
|
||||||
;; keyword args in a define-module form are not regular
|
(define (keyword-like? stx)
|
||||||
;; (i.e. no-backtrace doesn't take a value).
|
(let ((dat (syntax->datum stx)))
|
||||||
(let loop ((compiled-args `((quote ,(car args))))
|
(and (symbol? dat)
|
||||||
(args (cdr args)))
|
(eqv? (string-ref (symbol->string dat) 0) #\:))))
|
||||||
(cond ((null? args)
|
(define (->keyword sym)
|
||||||
(reverse! compiled-args))
|
(symbol->keyword (string->symbol (substring (symbol->string sym) 1))))
|
||||||
;; symbol in keyword position
|
|
||||||
((symbol? (car args))
|
(define (quotify-iface args)
|
||||||
(loop compiled-args
|
(let loop ((in args) (out '()))
|
||||||
(cons (keyword-like-symbol->keyword (car args)) (cdr args))))
|
(syntax-case in ()
|
||||||
((memq (car args) '(#:no-backtrace #:pure))
|
(() (reverse! out))
|
||||||
(loop (cons (car args) compiled-args)
|
;; The user wanted #:foo, but wrote :foo. Fix it.
|
||||||
(cdr args)))
|
((sym . in) (keyword-like? #'sym)
|
||||||
((null? (cdr args))
|
(loop #`(#,(->keyword (syntax->datum #'sym)) . in) out))
|
||||||
(error "keyword without value:" (car args)))
|
((kw . in) (not (keyword? (syntax->datum #'kw)))
|
||||||
((memq (car args) '(#:use-module #:use-syntax))
|
(syntax-violation 'define-module "expected keyword arg" x #'kw))
|
||||||
(loop (cons* `(list ,@(compile-interface-spec (cadr args)))
|
((#:renamer renamer . in)
|
||||||
(car args)
|
(loop #'in (cons* #'renamer #:renamer out)))
|
||||||
compiled-args)
|
((kw val . in)
|
||||||
(cddr args)))
|
(loop #'in (cons* #''val #'kw out))))))
|
||||||
((eq? (car args) #:autoload)
|
|
||||||
(loop (cons* `(quote ,(caddr args))
|
|
||||||
`(quote ,(cadr args))
|
|
||||||
(car args)
|
|
||||||
compiled-args)
|
|
||||||
(cdddr args)))
|
|
||||||
(else
|
|
||||||
(loop (cons* `(quote ,(cadr args))
|
|
||||||
(car args)
|
|
||||||
compiled-args)
|
|
||||||
(cddr args))))))
|
|
||||||
|
|
||||||
(defmacro define-module args
|
(define (quotify args)
|
||||||
`(eval-when
|
;; Just quote everything except #:use-module and #:use-syntax. We
|
||||||
(eval load compile)
|
;; need to know about all arguments regardless since we want to turn
|
||||||
(let ((m (process-define-module
|
;; symbols that look like keywords into real keywords, and the
|
||||||
(list ,@(compile-define-module-args args)))))
|
;; keyword args in a define-module form are not regular
|
||||||
(set-current-module m)
|
;; (i.e. no-backtrace doesn't take a value).
|
||||||
m)))
|
(let loop ((in args) (out '()))
|
||||||
|
(syntax-case in ()
|
||||||
|
(() (reverse! out))
|
||||||
|
;; The user wanted #:foo, but wrote :foo. Fix it.
|
||||||
|
((sym . in) (keyword-like? #'sym)
|
||||||
|
(loop #`(#,(->keyword (syntax->datum #'sym)) . in) out))
|
||||||
|
((kw . in) (not (keyword? (syntax->datum #'kw)))
|
||||||
|
(syntax-violation 'define-module "expected keyword arg" x #'kw))
|
||||||
|
((#:no-backtrace . in)
|
||||||
|
(loop #'in (cons #:no-backtrace out)))
|
||||||
|
((#:pure . in)
|
||||||
|
(loop #'in (cons #:pure out)))
|
||||||
|
((kw)
|
||||||
|
(syntax-violation 'define-module "keyword arg without value" x #'kw))
|
||||||
|
((use-module (name name* ...) . in)
|
||||||
|
(and (memq (syntax->datum #'use-module) '(#:use-module #:use-syntax))
|
||||||
|
(and-map symbol? (syntax->datum #'(name name* ...))))
|
||||||
|
(loop #'in
|
||||||
|
(cons* #''((name name* ...))
|
||||||
|
#'use-module
|
||||||
|
out)))
|
||||||
|
((use-module ((name name* ...) arg ...) . in)
|
||||||
|
(and (memq (syntax->datum #'use-module) '(#:use-module #:use-syntax))
|
||||||
|
(and-map symbol? (syntax->datum #'(name name* ...))))
|
||||||
|
(loop #'in
|
||||||
|
(cons* #`(list '(name name* ...) #,@(quotify-iface #'(arg ...)))
|
||||||
|
#'use-module
|
||||||
|
out)))
|
||||||
|
((#:autoload name bindings . in)
|
||||||
|
(loop #'in (cons* #''bindings #''name #:autoload out)))
|
||||||
|
((kw val . in)
|
||||||
|
(loop #'in (cons* #''val #'kw out))))))
|
||||||
|
|
||||||
|
(syntax-case x ()
|
||||||
|
((_ (name name* ...) arg ...)
|
||||||
|
(with-syntax (((quoted-arg ...) (quotify #'(arg ...))))
|
||||||
|
#'(eval-when (eval load compile)
|
||||||
|
(let ((m (process-define-module
|
||||||
|
(list '(name name* ...) quoted-arg ...))))
|
||||||
|
(set-current-module m)
|
||||||
|
m)))))))
|
||||||
|
|
||||||
;; The guts of the use-modules macro. Add the interfaces of the named
|
;; The guts of the use-modules macro. Add the interfaces of the named
|
||||||
;; modules to the use-list of the current module, in order.
|
;; modules to the use-list of the current module, in order.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue