Hi, The patch below adds a `#:reader' keyword to `define-module' that allows modules to specify the reader that should be used to interpret them:
(define-module (the-module) #:reader the-reader-for-my-favorite-syntax) This way, module implementors can decide to use whatever syntax variant they prefer, while not having any side-effect on the code being read from other files or modules. For illustration, here is an example that makes use of my `guile-reader' thing: --8<---------------cut here---------------start------------->8--- (define-module (module-with-reader) #:reader (let* ((elisp-char-tr (make-token-reader #\? (token-reader-procedure (standard-token-reader 'character))))) (make-reader (cons elisp-char-tr (map standard-token-reader '(whitespace sexp string number colon-keyword semicolon-comment symbol-upper-case symbol-lower-case quote-quasiquote-unquote))))) #:use-module (system reader)) (define-public (return-a-colon-keyword) :a-keyword!) (define-public (return-an-elisp-character) ?a) --8<---------------cut here---------------end--------------->8--- For the module user, things are completely transparent: $ guile -L . guile> (read-options) (keywords #f positions) guile> (use-modules (module-with-reader)) guile> (return-a-colon-keyword) #:a-keyword! guile> (return-an-elisp-character) #\a guile> (module-reader (resolve-module '(module-with-reader))) #<reader 301c2328> guile> (module-reader (current-module)) #<primitive-procedure read> The patch has a slight impact on `boot-9.scm' and `load.c'. The procedure `primitive-load' (which is called by `load-module') is modified in order to switch to the current module's reader as soon as the current module changes. Feedback welcome! ;-) Thanks, Ludovic. ChangeLog entry for `libguile': 2005-10-13 Ludovic Courtès <[EMAIL PROTECTED]> * load.c (scm_primitive_load): Switch to the current module's reader when the current module changes. * module.h (scm_module_index_reader): New macro. (SCM_MODULE_READER): New macro. ChangeLog entry for `ice-9': 2005-10-13 Ludovic Courtès <[EMAIL PROTECTED]> * boot-9.scm (module-type): New field `reader'. Updated callers of `module-constructor'. (module-reader): New procedure. (set-module-reader!): New procedure. (process-define-module): Handle the `#:reader' keyword. Index: ice-9/boot-9.scm =================================================================== RCS file: /cvsroot/guile/guile/guile-core/ice-9/boot-9.scm,v retrieving revision 1.351 diff -u -B -b -p -r1.351 boot-9.scm --- ice-9/boot-9.scm 31 Jul 2005 23:36:50 -0000 1.351 +++ ice-9/boot-9.scm 13 Sep 2005 12:28:08 -0000 @@ -1185,7 +1185,8 @@ (make-record-type 'module '(obarray uses binder eval-closure transformer name kind duplicates-handlers duplicates-interface - observers weak-observers observer-id) + observers weak-observers observer-id + reader) %print-module)) ;; make-module &opt size uses binder @@ -1221,7 +1222,8 @@ uses binder #f #f #f #f #f #f '() (make-weak-value-hash-table 31) - 0))) + 0 + read))) ;; We can't pass this as an argument to module-constructor, ;; because we need it to close over a pointer to the module @@ -1247,6 +1249,8 @@ (define set-module-name! (record-modifier module-type 'name)) (define module-kind (record-accessor module-type 'kind)) (define set-module-kind! (record-modifier module-type 'kind)) +(define module-reader (record-accessor module-type 'reader)) +(define set-module-reader! (record-modifier module-type 'reader)) (define module-duplicates-handlers (record-accessor module-type 'duplicates-handlers)) (define set-module-duplicates-handlers! @@ -2042,10 +2046,22 @@ (call-with-deferred-observers (lambda () (module-use-interfaces! module (reverse reversed-interfaces)) + ;; Evaluate the `#:reader' argument in the context of the module + ;; being defined. + (set-module-reader! module + (eval (module-reader module) module)) (module-export! module exports) (module-replace! module replacements) (module-re-export! module re-exports))) (case (car kws) + ((#:reader) + ;; The argument to `#:reader' will be evaluated eventually. + (set-module-reader! module (cadr kws)) + (loop (cddr kws) + reversed-interfaces + exports + re-exports + replacements)) ((#:use-module #:use-syntax) (or (pair? (cdr kws)) (unrecognized kws)) @@ -2138,7 +2154,7 @@ (set-car! (memq a (module-uses module)) i) (module-local-variable i sym)))))) (module-constructor (make-hash-table 0) '() b #f #f name 'autoload #f #f - '() (make-weak-value-hash-table 31) 0))) + '() (make-weak-value-hash-table 31) 0 read))) ;;; {Compiled module} Index: libguile/load.c =================================================================== RCS file: /cvsroot/guile/guile/guile-core/libguile/load.c,v retrieving revision 1.86 diff -u -B -b -p -r1.86 load.c --- libguile/load.c 23 May 2005 19:57:20 -0000 1.86 +++ libguile/load.c 13 Sep 2005 12:28:08 -0000 @@ -82,15 +82,29 @@ SCM_DEFINE (scm_primitive_load, "primiti scm_call_1 (hook, filename); { /* scope */ + SCM module = SCM_BOOL_F, reader = SCM_BOOL_F; SCM port = scm_open_file (filename, scm_from_locale_string ("r")); scm_frame_begin (SCM_F_FRAME_REWINDABLE); scm_i_frame_current_load_port (port); while (1) { - SCM form = scm_read (port); + SCM form; + + if (scm_current_module () != module) + { + module = scm_current_module (); + reader = SCM_MODULE_READER (module); + } + + if (reader == SCM_BOOL_F) + form = scm_read (port); + else + form = scm_call_1 (reader, port); + if (SCM_EOF_OBJECT_P (form)) break; + scm_primitive_eval_x (form); } Index: libguile/modules.h =================================================================== RCS file: /cvsroot/guile/guile/guile-core/libguile/modules.h,v retrieving revision 1.28 diff -u -B -b -p -r1.28 modules.h --- libguile/modules.h 31 Jul 2005 23:36:14 -0000 1.28 +++ libguile/modules.h 13 Sep 2005 12:28:08 -0000 @@ -45,6 +45,7 @@ SCM_API scm_t_bits scm_module_tag; #define scm_module_index_binder 2 #define scm_module_index_eval_closure 3 #define scm_module_index_transformer 4 +#define scm_module_index_reader 12 #define SCM_MODULE_OBARRAY(module) \ SCM_PACK (SCM_STRUCT_DATA (module) [scm_module_index_obarray]) @@ -56,6 +57,8 @@ SCM_API scm_t_bits scm_module_tag; SCM_PACK (SCM_STRUCT_DATA (module)[scm_module_index_eval_closure]) #define SCM_MODULE_TRANSFORMER(module) \ SCM_PACK (SCM_STRUCT_DATA (module)[scm_module_index_transformer]) +#define SCM_MODULE_READER(module) \ + SCM_PACK (SCM_STRUCT_DATA (module)[scm_module_index_reader]) SCM_API scm_t_bits scm_tc16_eval_closure; _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel