~ chicken-core (chicken-5) a42607e61cbfe6bad64ac68cc37c1577052bd33e
commit a42607e61cbfe6bad64ac68cc37c1577052bd33e Author: felix <felix@call-with-current-continuation.org> AuthorDate: Thu Aug 23 21:47:35 2012 +0200 Commit: Christian Kellermann <ckeen@pestilenz.org> CommitDate: Tue Aug 28 09:22:54 2012 +0200 Fix problems with `reexport'. This patch fixes the bugs #900 and #901 (both reported by megane): * When reexporting syntax in a module with "*" export list, the syntax must be added to the modules' "exist" list, so that it can be retrieved on import. * When reexporting, indirect exports (of the form "(<syntax> <name> ...)") must be copied from the module that is reexported into the module that reexports, to make them available in the importing module (reexported syntactic bindings may refer to indirect exports, but these do not exist in the wrapper, the module that does the reexport. Yes, this is quite confusing). Test cases have been added. Signed-off-by: Christian Kellermann <ckeen@pestilenz.org> diff --git a/distribution/manifest b/distribution/manifest index 4be115b0..9f63422f 100644 --- a/distribution/manifest +++ b/distribution/manifest @@ -154,7 +154,10 @@ tests/syntax-tests-2.scm tests/meta-syntax-test.scm tests/reexport-m1.scm tests/reexport-m2.scm +tests/reexport-m3.scm +tests/reexport-m4.scm tests/reexport-tests.scm +tests/reexport-tests-2.scm tests/ec.scm tests/ec-tests.scm tests/test-chained-modules.scm diff --git a/modules.scm b/modules.scm index 078da0d0..b1571c2e 100644 --- a/modules.scm +++ b/modules.scm @@ -83,12 +83,13 @@ module-exist-list set-module-exist-list! module-meta-expressions set-module-meta-expressions! module-defined-syntax-list set-module-defined-syntax-list! - module-saved-environments set-module-saved-environments!)) + module-saved-environments set-module-saved-environments! + module-iexports set-module-iexports!)) (define-record-type module (%make-module name export-list defined-list exist-list defined-syntax-list undefined-list import-forms meta-import-forms meta-expressions - vexports sexports saved-environments) + vexports sexports iexports saved-environments) module? (name module-name) ; SYMBOL (export-list module-export-list set-module-export-list!) ; (SYMBOL | (SYMBOL ...) ...) @@ -101,6 +102,7 @@ (meta-expressions module-meta-expressions set-module-meta-expressions!) ; (EXP ...) (vexports module-vexports set-module-vexports!) ; ((SYMBOL . SYMBOL) ...) (sexports module-sexports set-module-sexports!) ; ((SYMBOL SE TRANSFORMER) ...) + (iexports module-iexports set-module-iexports!) ; ((SYMBOL . SYMBOL) ...) ;; for csi's ",m" command, holds (<env> . <macroenv>) (saved-environments module-saved-environments set-module-saved-environments!)) @@ -112,8 +114,8 @@ (module-vexports m) (module-sexports m))) -(define (make-module name explist vexports sexports) - (%make-module name explist '() '() '() '() '() '() '() vexports sexports #f)) +(define (make-module name explist vexports sexports iexports) + (%make-module name explist '() '() '() '() '() '() '() vexports sexports iexports #f)) (define (##sys#register-module-alias alias name) (##sys#module-alias-environment @@ -170,8 +172,7 @@ exps) (set-module-sexports! mod (append sexps (module-sexports mod))) (set-module-exist-list! mod (append el exps))) - (set-module-export-list! - mod (append xl exps))))) + (set-module-export-list! mod (append xl exps))))) (define (##sys#toplevel-definition-hook sym mod exp val) #f) @@ -236,7 +237,7 @@ (cons (cons sym (if where (list where) '())) ul))))))) (define (##sys#register-module name explist #!optional (vexports '()) (sexports '())) - (let ((mod (make-module name explist vexports sexports))) + (let ((mod (make-module name explist vexports sexports '()))) (set! ##sys#module-table (cons (cons name mod) ##sys#module-table)) mod) ) @@ -318,7 +319,7 @@ (if (symbol? (cdr ie)) `'(,(car ie) . ,(cdr ie)) `(list ',(car ie) '() ,(cdr ie)))) - (module-indirect-exports mod))) + (module-iexports mod))) ',(module-vexports mod) (list ,@(map (lambda (sexport) @@ -366,7 +367,7 @@ (map (lambda (ne) (list (car ne) #f (##sys#ensure-transformer (cdr ne) (car ne)))) sdefs)) - (mod (make-module name '() vexports sexps)) + (mod (make-module name '() vexports sexps iexps)) (senv (merge-se (##sys#macro-environment) (##sys#current-environment) @@ -411,7 +412,8 @@ "unknown syntax referenced while registering module" se name)) se)) - sexports)))) + sexports) + '()))) (set-module-saved-environments! mod (cons (merge-se (##sys#current-environment) @@ -540,6 +542,9 @@ (SEXPORTS: ,@(map-se sexports)))) (set-module-vexports! mod vexports) (set-module-sexports! mod sexports) + (set-module-iexports! + mod + (merge-se (module-iexports mod) iexports)) ; "reexport" may already have added some (set-module-saved-environments! mod (cons (merge-se (##sys#current-environment) vexports sexports) @@ -589,8 +594,9 @@ (define (import-name spec) (let* ((mod (##sys#find-module/import-library (##sys#strip-syntax spec) 'import)) (vexp (module-vexports mod)) - (sexp (module-sexports mod))) - (cons vexp sexp))) + (sexp (module-sexports mod)) + (iexp (module-iexports mod))) + (values vexp sexp iexp))) (define (import-spec spec) (cond ((symbol? spec) (import-name spec)) ((or (not (list? spec)) (< (length spec) 2)) @@ -600,69 +606,67 @@ (##sys#intern-symbol (##sys#string-append "srfi-" (##sys#number->string (cadr spec)))))) (else - (let* ((s (car spec)) - (imp (import-spec (cadr spec))) - (impv (car imp)) - (imps (cdr imp))) - (cond ((c %only s) - (##sys#check-syntax loc spec '(_ _ . #(symbol 0))) - (let ((ids (map resolve (cddr spec)))) - (let loop ((ids ids) (v '()) (s '())) - (cond ((null? ids) (cons v s)) - ((assq (car ids) impv) => - (lambda (a) - (loop (cdr ids) (cons a v) s))) - ((assq (car ids) imps) => - (lambda (a) - (loop (cdr ids) v (cons a s)))) - (else (loop (cdr ids) v s)))))) - ((c %except s) - (##sys#check-syntax loc spec '(_ _ . #(symbol 0))) - (let ((ids (map resolve (cddr spec)))) - (let loop ((impv impv) (v '())) - (cond ((null? impv) - (let loop ((imps imps) (s '())) - (cond ((null? imps) (cons v s)) - ((memq (caar imps) ids) (loop (cdr imps) s)) - (else (loop (cdr imps) (cons (car imps) s)))))) - ((memq (caar impv) ids) (loop (cdr impv) v)) - (else (loop (cdr impv) (cons (car impv) v))))))) - ((c %rename s) - (##sys#check-syntax loc spec '(_ _ . #((symbol symbol) 0))) - (let loop ((impv impv) (imps imps) (v '()) (s '()) (ids (cddr spec))) - (cond ((null? impv) - (cond ((null? imps) - (for-each - (lambda (id) - (##sys#warn "renamed identifier not imported" id) ) - ids) - (cons v s)) - ((assq (caar imps) ids) => - (lambda (a) - (loop impv (cdr imps) - v - (cons (cons (cadr a) (cdar imps)) s) - (##sys#delq a ids)))) - (else (loop impv (cdr imps) v (cons (car imps) s) ids)))) - ((assq (caar impv) ids) => - (lambda (a) - (loop (cdr impv) imps - (cons (cons (cadr a) (cdar impv)) v) - s - (##sys#delq a ids)))) - (else (loop (cdr impv) imps - (cons (car impv) v) - s ids))))) - ((c %prefix s) - (##sys#check-syntax loc spec '(_ _ _)) - (let ((pref (tostr (caddr spec)))) - (define (ren imp) - (cons - (##sys#string->symbol - (##sys#string-append pref (##sys#symbol->string (car imp))) ) - (cdr imp) ) ) - (cons (map ren impv) (map ren imps)))) - (else (##sys#syntax-error-hook loc "invalid import specification" spec))))))) + (let ((s (car spec))) + (let-values (((impv imps impi) (import-spec (cadr spec)))) + (cond ((c %only s) + (##sys#check-syntax loc spec '(_ _ . #(symbol 0))) + (let ((ids (map resolve (cddr spec)))) + (let loop ((ids ids) (v '()) (s '())) + (cond ((null? ids) (values v s impi)) + ((assq (car ids) impv) => + (lambda (a) + (loop (cdr ids) (cons a v) s))) + ((assq (car ids) imps) => + (lambda (a) + (loop (cdr ids) v (cons a s)))) + (else (loop (cdr ids) v s)))))) + ((c %except s) + (##sys#check-syntax loc spec '(_ _ . #(symbol 0))) + (let ((ids (map resolve (cddr spec)))) + (let loop ((impv impv) (v '())) + (cond ((null? impv) + (let loop ((imps imps) (s '())) + (cond ((null? imps) (values v s impi)) + ((memq (caar imps) ids) (loop (cdr imps) s)) + (else (loop (cdr imps) (cons (car imps) s)))))) + ((memq (caar impv) ids) (loop (cdr impv) v)) + (else (loop (cdr impv) (cons (car impv) v))))))) + ((c %rename s) + (##sys#check-syntax loc spec '(_ _ . #((symbol symbol) 0))) + (let loop ((impv impv) (imps imps) (v '()) (s '()) (ids (cddr spec))) + (cond ((null? impv) + (cond ((null? imps) + (for-each + (lambda (id) + (##sys#warn "renamed identifier not imported" id) ) + ids) + (values v s impi)) + ((assq (caar imps) ids) => + (lambda (a) + (loop impv (cdr imps) + v + (cons (cons (cadr a) (cdar imps)) s) + (##sys#delq a ids)))) + (else (loop impv (cdr imps) v (cons (car imps) s) ids)))) + ((assq (caar impv) ids) => + (lambda (a) + (loop (cdr impv) imps + (cons (cons (cadr a) (cdar impv)) v) + s + (##sys#delq a ids)))) + (else (loop (cdr impv) imps + (cons (car impv) v) + s ids))))) + ((c %prefix s) + (##sys#check-syntax loc spec '(_ _ _)) + (let ((pref (tostr (caddr spec)))) + (define (ren imp) + (cons + (##sys#string->symbol + (##sys#string-append pref (##sys#symbol->string (car imp))) ) + (cdr imp) ) ) + (values (map ren impv) (map ren imps) impi))) + (else (##sys#syntax-error-hook loc "invalid import specification" spec)))))))) (##sys#check-syntax loc x '(_ . #(_ 1))) (let ((cm (##sys#current-module))) (when cm @@ -676,58 +680,60 @@ (append (module-import-forms cm) (cdr x))))) (for-each (lambda (spec) - (let* ((vs (import-spec spec)) - (vsv (car vs)) - (vss (cdr vs)) - (prims '())) - (dd `(IMPORT: ,loc)) - (dd `(V: ,(if cm (module-name cm) '<toplevel>) ,(map-se vsv))) - (dd `(S: ,(if cm (module-name cm) '<toplevel>) ,(map-se vss))) - (##sys#mark-imported-symbols vsv) ; mark imports as ##core#aliased - (for-each - (lambda (imp) - (let* ((id (car imp)) - (aid (cdr imp)) - (prim (getp aid '##core#primitive))) - (when prim - (set! prims (cons imp prims))) - (and-let* ((a (assq id (import-env))) - ((not (eq? aid (cdr a))))) - (##sys#notice "re-importing already imported identifier" id)))) - vsv) - (for-each - (lambda (imp) - (and-let* ((a (assq (car imp) (macro-env))) - ((not (eq? (cdr imp) (cdr a))))) - (##sys#notice "re-importing already imported syntax" (car imp))) ) - vss) - (when reexp? - (unless cm - (##sys#syntax-error-hook loc "`reexport' only valid inside a module")) - - (if (eq? #t (module-export-list cm)) - (begin - (set-module-exist-list! - cm - (append (module-exist-list cm) - (map car vsv) - (map car vss)))) - (set-module-export-list! + (let-values (((vsv vss vsi) (import-spec spec))) + (let ((prims '())) + (dd `(IMPORT: ,loc)) + (dd `(V: ,(if cm (module-name cm) '<toplevel>) ,(map-se vsv))) + (dd `(S: ,(if cm (module-name cm) '<toplevel>) ,(map-se vss))) + (##sys#mark-imported-symbols vsv) ; mark imports as ##core#aliased + (for-each + (lambda (imp) + (let* ((id (car imp)) + (aid (cdr imp)) + (prim (getp aid '##core#primitive))) + (when prim + (set! prims (cons imp prims))) + (and-let* ((a (assq id (import-env))) + ((not (eq? aid (cdr a))))) + (##sys#notice "re-importing already imported identifier" id)))) + vsv) + (for-each + (lambda (imp) + (and-let* ((a (assq (car imp) (macro-env))) + ((not (eq? (cdr imp) (cdr a))))) + (##sys#notice "re-importing already imported syntax" (car imp))) ) + vss) + (when reexp? + (unless cm + (##sys#syntax-error-hook loc "`reexport' only valid inside a module")) + (let ((el (module-export-list cm))) + (cond ((eq? #t el) + (set-module-sexports! cm (append vss (module-sexports cm))) + (set-module-exist-list! + cm + (append (module-exist-list cm) + (map car vsv) + (map car vss)))) + (else + (set-module-export-list! + cm + (append + (let ((xl (module-export-list cm))) + (if (eq? #t xl) '() xl)) + (map car vsv) + (map car vss)))))) + (set-module-iexports! + cm + (merge-se (module-iexports cm) vsi)) + (when (pair? prims) + (set-module-meta-expressions! cm (append - (let ((xl (module-export-list cm) )) - (if (eq? #t xl) '() xl)) - (map car vsv) - (map car vss)))) - (when (pair? prims) - (set-module-meta-expressions! - cm - (append - (module-meta-expressions cm) - `((##sys#mark-primitive ',prims))))) - (dm "export-list: " (module-export-list cm))) - (import-env (append vsv (import-env))) - (macro-env (append vss (macro-env))))) + (module-meta-expressions cm) + `((##sys#mark-primitive ',prims))))) + (dm "export-list: " (module-export-list cm))) + (import-env (append vsv (import-env))) + (macro-env (append vss (macro-env)))))) (cdr x)) '(##core#undefined)))) diff --git a/tests/reexport-m1.scm b/tests/reexport-m1.scm index e08ddb58..96ac9bc1 100644 --- a/tests/reexport-m1.scm +++ b/tests/reexport-m1.scm @@ -1,3 +1,5 @@ +;;;; module re-exporting from core module + (module reexport-m1 () (import scheme chicken) (require-library srfi-1 srfi-13) diff --git a/tests/reexport-m2.scm b/tests/reexport-m2.scm index ec955f39..daee95f8 100644 --- a/tests/reexport-m2.scm +++ b/tests/reexport-m2.scm @@ -1,3 +1,5 @@ +;;;; module importing from module that reexports core binding + (module foo () (import scheme chicken) (use reexport-m1) diff --git a/tests/reexport-m3.scm b/tests/reexport-m3.scm new file mode 100644 index 00000000..202e6b30 --- /dev/null +++ b/tests/reexport-m3.scm @@ -0,0 +1,9 @@ +(module + reexport-m3 + ((foo bar)) + (import chicken scheme) + (define (bar) 1) + (define-syntax foo + (ir-macro-transformer + (lambda (e i c) + `(bar))))) diff --git a/tests/reexport-m4.scm b/tests/reexport-m4.scm new file mode 100644 index 00000000..c81287bc --- /dev/null +++ b/tests/reexport-m4.scm @@ -0,0 +1,10 @@ +(module + reexport-m4 + (baz) + (import chicken scheme) + (use reexport-m3) + (reexport reexport-m3) + (define-syntax baz + (ir-macro-transformer + (lambda (e i c) + `(foo))))) diff --git a/tests/reexport-tests-2.scm b/tests/reexport-tests-2.scm new file mode 100644 index 00000000..35ef76db --- /dev/null +++ b/tests/reexport-tests-2.scm @@ -0,0 +1,2 @@ +(use reexport-m4) +(print (baz)) diff --git a/tests/reexport-tests.scm b/tests/reexport-tests.scm index 892ad643..651ed476 100644 --- a/tests/reexport-tests.scm +++ b/tests/reexport-tests.scm @@ -36,3 +36,23 @@ (module m3 () (import scheme big-chicken) (pp (string-intersperse '("abc" "def" "ghi") "-"))) + +;;; #901 - reexport with "*" export list + +(module + m4 + (foo-m4) + (import chicken scheme) + (define-syntax foo-m4 + (ir-macro-transformer + (lambda (e i c) + ''1)))) + +(module + m5 + * ; () works here + (import chicken scheme) + (reexport m4)) + +(import m5) +(print (foo-m4)) diff --git a/tests/runtests.sh b/tests/runtests.sh index 469ccd41..5b6113e8 100755 --- a/tests/runtests.sh +++ b/tests/runtests.sh @@ -196,6 +196,10 @@ $compile_s reexport-m1.import.scm $interpret -s reexport-m2.scm $compile reexport-m2.scm ./a.out +$compile_s reexport-m3.scm -J +$compile_s reexport-m4.scm -J +$compile reexport-tests-2.scm +./a.out echo "======================================== functor tests ..." $interpret -bnq simple-functors-test.scmTrap