~ chicken-core (chicken-5) d2d195ac1757b86caaf503535da97b1afc604b85
commit d2d195ac1757b86caaf503535da97b1afc604b85 Author: Evan Hanson <evhan@foldling.org> AuthorDate: Fri Oct 9 20:36:33 2015 +1300 Commit: Peter Bex <peter@more-magic.net> CommitDate: Mon Nov 2 21:29:01 2015 +0100 Add support for library lists in functors and functor arguments Also removes the syntax for creating module aliases to avoid ambiguity between that and instantiation of a functor with a list-style name. diff --git a/NEWS b/NEWS index 19b69369..eba4c910 100644 --- a/NEWS +++ b/NEWS @@ -28,6 +28,7 @@ program's (macro) namespace anymore. - The core units have been converted to modules under the "chicken" namespace. + - Added support for list-style library names. 4.10.2 diff --git a/chicken-syntax.scm b/chicken-syntax.scm index a739cb51..6464808c 100644 --- a/chicken-syntax.scm +++ b/chicken-syntax.scm @@ -1138,7 +1138,7 @@ 'functor '() (##sys#er-transformer (lambda (x r c) - (##sys#check-syntax 'functor x '(_ (symbol . #((_ _) 0)) _ . _)) + (##sys#check-syntax 'functor x '(_ (_ . #((_ _) 0)) _ . _)) (let* ((x (chicken.expand#strip-syntax x)) (head (cadr x)) (name (car head)) @@ -1147,7 +1147,7 @@ (body (cdddr x)) (registration `(##sys#register-functor - ',name + ',(chicken.internal#library-id name) ',(map (lambda (arg) (let ((argname (car arg)) (exps (##sys#validate-exports (cadr arg) 'functor))) @@ -1155,14 +1155,17 @@ (and (list? argname) (= 2 (length argname)) (symbol? (car argname)) - (symbol? (cadr argname)))) + (let ((param (cadr argname))) + (or (symbol? param) + (and (list? param) + (every symbol? param)))))) (##sys#syntax-error-hook "invalid functor argument" name arg)) (cons argname exps))) args) ',(##sys#validate-exports exps 'functor) ',body))) `(##core#module - ,name + ,(chicken.internal#library-id name) #t (import scheme chicken) (begin-for-syntax ,registration)))))) diff --git a/expand.scm b/expand.scm index e7ad3a13..257214d9 100644 --- a/expand.scm +++ b/expand.scm @@ -1448,38 +1448,34 @@ (cond ((and (fx>= len 4) (c (r '=) (caddr x))) (let* ((x (chicken.expand#strip-syntax x)) (app (cadddr x))) - (cond ((symbol? app) - (cond ((fx> len 4) - ;; feature suggested by syn: - ;; - ;; (module NAME = FUNCTORNAME BODY ...) - ;; ~> - ;; (begin - ;; (module _NAME * BODY ...) - ;; (module NAME = (FUNCTORNAME _NAME))) - ;; - ;; - the use of "_NAME" is a bit stupid, but it must be - ;; externally visible to generate an import library from - ;; and compiling "NAME" separately may need an import-lib - ;; for stuff in "BODY" (say, syntax needed by syntax exported - ;; from the functor, or something like this...) - (let ((mtmp (string->symbol - (##sys#string-append - "_" - (symbol->string name)))) - (%module (r 'module))) - `(##core#begin - (,%module ,mtmp * ,@(cddddr x)) - (,%module ,name = (,app ,mtmp))))) - (else - (##sys#register-module-alias name app) - '(##core#undefined)))) + (cond ((fx> len 4) + ;; feature suggested by syn: + ;; + ;; (module NAME = FUNCTORNAME BODY ...) + ;; ~> + ;; (begin + ;; (module _NAME * BODY ...) + ;; (module NAME = (FUNCTORNAME _NAME))) + ;; + ;; - the use of "_NAME" is a bit stupid, but it must be + ;; externally visible to generate an import library from + ;; and compiling "NAME" separately may need an import-lib + ;; for stuff in "BODY" (say, syntax needed by syntax exported + ;; from the functor, or something like this...) + (let ((mtmp (string->symbol + (##sys#string-append + "_" + (symbol->string name)))) + (%module (r 'module))) + `(##core#begin + (,%module ,mtmp * ,@(cddddr x)) + (,%module ,name = (,app ,mtmp))))) (else (##sys#check-syntax - 'module x '(_ symbol _ (symbol . #(_ 0)))) + 'module x '(_ _ _ (_ . #(_ 0)))) (##sys#instantiate-functor name - (car app) ; functor name + (chicken.internal#library-id (car app)) (cdr app)))))) ; functor arguments (else ;;XXX use module name in "loc" argument? diff --git a/manual/Modules b/manual/Modules index 34da3bbd..57a0c9d8 100644 --- a/manual/Modules +++ b/manual/Modules @@ -43,8 +43,8 @@ CHICKEN's module system has the following features: <macro>(module NAME (EXPORT ...) BODY ...)</macro> <macro>(module NAME (EXPORT ...) FILENAME)</macro> <macro>(module NAME * BODY ...)</macro> -<macro>(module NAME1 = NAME2 [BODY ...])</macro> <macro>(module NAME = (FUNCTORNAME MODULENAME1 ...))</macro> +<macro>(module NAME = FUNCTORNAME BODY ...)</macro> Defines a module with the name {{NAME}}, a set of exported bindings and a contained sequence of toplevel expressions that are evaluated in @@ -79,15 +79,12 @@ like {{(include FILENAME)}}. {{(module NAME = (FUNCTORNAME MODULENAME1 ...))}} instantiates a ''functor'' (see below for information about functors). -The syntax {{(module NAME1 = NAME2)}} defines an alias {{NAME1}} for -the module {{NAME2}}, so {{NAME1}} can be used in place of {{NAME2}} -in all forms that accept module names. Module aliases defined inside a -module are local to that module. If followed by a module body, then -this is a special form of ''functor instantiation''. +{{(module NAME = FUNCTORNAME BODY ...)}} is a special form of +''functor instantiation'' where the {{BODY}} implements a module +satisfying a single functor argument to {{FUNCTORNAME}}. Nested modules, modules not at toplevel (i.e. local modules) or -mutually recursive modules are not supported. As an exception -module alias definitions are allowed inside a module definition. +mutually recursive modules are not supported. When compiled, the module information, including exported macros is stored in the generated binary and available when loading @@ -265,7 +262,7 @@ available: [module] r4rs [module] r5rs -Exports the definitions given in R4RS or R5RS. {{r5rs}} is a module alias +Exports the definitions given in R4RS or R5RS. {{r5rs}} is an alias for {{scheme}}. [module] chicken diff --git a/modules.scm b/modules.scm index 5afdbbf4..ae4452ae 100644 --- a/modules.scm +++ b/modules.scm @@ -840,9 +840,9 @@ '() (let ((p (car fas))) (if (pair? (car p)) ; has default argument? - (let ((alias (caar p)) - (mname (cadar p)) - (exps (cdr p))) + (let ((exps (cdr p)) + (alias (caar p)) + (mname (chicken.internal#library-id (cadar p)))) (##sys#match-functor-argument alias name mname exps fname) (cons (list alias mname) (loop2 (cdr fas)))) ;; no default argument, we have too few argument modules @@ -853,10 +853,10 @@ ;; otherwise match provided argument to functor argument (let* ((p (car fas)) (p1 (car p)) + (exps (cdr p)) (def? (pair? p1)) (alias (if def? (car p1) p1)) - (mname (car as)) - (exps (cdr p))) + (mname (chicken.internal#library-id (car as)))) (##sys#match-functor-argument alias name mname exps fname) (cons (list alias mname) (loop (cdr as) (cdr fas))))))) diff --git a/tests/functor-tests.scm b/tests/functor-tests.scm index 1c71ddf2..5db07414 100644 --- a/tests/functor-tests.scm +++ b/tests/functor-tests.scm @@ -1,7 +1,7 @@ ;;;; functor-tests.scm -(use data-structures extras) +(use data-structures extras ports) (include "test.scm") @@ -101,6 +101,35 @@ ;;XXX shows (""), which looks wrong: (pp (show 8 (search next-char '()))) ;XXX assert +;; list-style library names + +(functor ((double printer) ((P (chicken)) (print))) (print-twice) + (import (scheme) P) + (define (print-twice x) (print x) (print x))) + +(module (noop printer) * + (import (only (scheme) define) (only (chicken) void)) + (define print void)) + +(module (2x print) = ((double printer))) + +(module (2x noop) = ((double printer) (noop printer))) + +(module (2x write) = (double printer) + (reexport (rename (scheme) (write print)))) + +(define output + (with-output-to-string + (lambda () + (import (2x print)) + (print-twice #\a) + (import (2x noop)) + (print-twice #\a) + (import (2x write)) + (print-twice #\a)))) + +(test-equal "double printer" output "a\na\n#\\a#\\a") + ;; Test for errors #+csi diff --git a/tests/module-tests.scm b/tests/module-tests.scm index df782a98..421560e6 100644 --- a/tests/module-tests.scm +++ b/tests/module-tests.scm @@ -197,7 +197,8 @@ 'abc (abc)) (module m17 (a) (import scheme) (define a 1)) -(module m18 = m17) +(begin-for-syntax ; XXX workaround for missing module alias functionality + (##sys#register-module-alias 'm18 'm17)) (module m19 (a) (import scheme) (define a 2)) (test-equal @@ -212,7 +213,8 @@ "local module alias scope" (module m21 () (import scheme) - (module m18 = m19) + (begin-for-syntax ; XXX s.a. + (##sys#register-module-alias 'm18 'm19)) (import m18) a) 2) @@ -298,6 +300,22 @@ (m29-baz)) 'foo) +;; list-style library names + +(test-assert + (module (m33 a) * + (import (scheme)) + (define (foo) 'ok))) + +(test-assert + (module (m33 b) () + (import (scheme) (m33 a)) + (eq? (foo) 'ok))) + +(test-assert (import (prefix (m33 a) m33/a/))) +(test-assert (eq? (m33/a/foo) 'ok)) +(test-assert (module-environment '(m33 a))) + ;; Ensure that the modules system is simply an aliasing mechanism: ;; Module instantion does not create multiple variable copies. diff --git a/tests/simple-functors-test.scm b/tests/simple-functors-test.scm index f72e9662..3e69a3db 100644 --- a/tests/simple-functors-test.scm +++ b/tests/simple-functors-test.scm @@ -8,14 +8,12 @@ (define a 1) (define b 2)) -(module f = foo) - (functor (do-things (arg STUFF)) (do-it) (import scheme arg) (define (do-it) (list a b))) -(module bar = (do-things f)) +(module bar = (do-things foo)) (import bar) (assert (equal? '(1 2) (do-it)))Trap