1
Fork 0
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:
Andy Wingo 2010-05-03 15:38:29 +02:00
parent a40e1c9078
commit 074e036ee2

View file

@ -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.