* [PATCH] Per-module reader @ 2005-09-13 12:51 Ludovic Courtès 2005-09-26 12:29 ` Ludovic Courtès 2005-09-26 19:05 ` Neil Jerram 0 siblings, 2 replies; 50+ messages in thread From: Ludovic Courtès @ 2005-09-13 12:51 UTC (permalink / raw) 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 <ludovic.courtes@laas.fr> * 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 <ludovic.courtes@laas.fr> * 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 ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader 2005-09-13 12:51 [PATCH] Per-module reader Ludovic Courtès @ 2005-09-26 12:29 ` Ludovic Courtès 2005-09-26 22:55 ` Kevin Ryde 2005-09-26 19:05 ` Neil Jerram 1 sibling, 1 reply; 50+ messages in thread From: Ludovic Courtès @ 2005-09-26 12:29 UTC (permalink / raw) Hello, Could someone comment on this patch? (see <87u0gp9lm3.fsf@laas.fr>) It's actually quite trivial. :-) Thanks in advance, Ludovic. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader 2005-09-26 12:29 ` Ludovic Courtès @ 2005-09-26 22:55 ` Kevin Ryde 2005-09-27 9:04 ` Ludovic Courtès 0 siblings, 1 reply; 50+ messages in thread From: Kevin Ryde @ 2005-09-26 22:55 UTC (permalink / raw) ludovic.courtes@laas.fr (Ludovic Courtès) writes: > > Could someone comment on this patch? (see <87u0gp9lm3.fsf@laas.fr>) > It's actually quite trivial. :-) I have doubts. Can you give more examples of when it might be used? Elisp syntax is probably not a good example, since elisp code wouldn't start with "define-module". Minor variants of syntax overall don't sound like a great idea to me, I would hope #,() and the guile #[whatever] is probably enough. For radically different syntax, a module could read and eval (or whatever) from `current-load-port' could it? _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader 2005-09-26 22:55 ` Kevin Ryde @ 2005-09-27 9:04 ` Ludovic Courtès 0 siblings, 0 replies; 50+ messages in thread From: Ludovic Courtès @ 2005-09-27 9:04 UTC (permalink / raw) Hi, Kevin Ryde <user42@zip.com.au> writes: > I have doubts. Can you give more examples of when it might be used? > Elisp syntax is probably not a good example, since elisp code wouldn't > start with "define-module". There are really two questions in your message. One is "do we really need syntax configuration beyond #,() and the likes?". The second one is "why would we write Guile modules that use a potentially significantly different syntax?" The per-module mechanisms is addressing the latter. My answer to the former is "yes" and `guile-reader' is trying to address this. The point is the following: one may wish to write a Guile module using her own syntax variant (no matter which one), yet want it to be well integrated into Guile's module hierarchy, correctly read, and not have unexpected side effects on the user's code. IMO, per-module readers are a way to fix the current scheme were there's only one instance of `read' and any module can happily modify it via `read-enable' and the likes. Ultimately, I'd be very glad if `read-enable', for instance, could translate into something like (%read-enable (module-reader (current-module)) something) In the end, `define-module' could almost be thought of as the Guile equivalent to the `#!' sequence found at the beginning of Unix scripts. As for syntax variants, my main interest currently is the syntax of Skribe[1] which borrows from Scheme, DSSSL, and also has special forms using square brackets. But again, that is a question relevant to `guile-reader' more than to the per-module reader mechanism. Thanks, Ludovic. [1] http://www-sop.inria.fr/mimosa/fp/Skribe/ _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader 2005-09-13 12:51 [PATCH] Per-module reader Ludovic Courtès 2005-09-26 12:29 ` Ludovic Courtès @ 2005-09-26 19:05 ` Neil Jerram 2005-09-27 8:21 ` Ludovic Courtès 1 sibling, 1 reply; 50+ messages in thread From: Neil Jerram @ 2005-09-26 19:05 UTC (permalink / raw) Cc: guile-devel ludovic.courtes@laas.fr (Ludovic Courtès) writes: > 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) All looks good, except for concerns about (i) performance; (ii) whether #:reader fits nicely in the big picture with the transformer option; (iii) one possible bug. > 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)) This is nice; but concerns about whether it fits with transformer are: - Transformer is specified with #:use-syntax followed by module name, which is a lot different from your syntax. I prefer your syntax, because use-syntax requires the transformer procedure to have the same name as the module it's defined in, which seems rubbish. But on the other hand perhaps there is a reason for forcing the reader/transformer to be defined in another module - are we missing some subtlety here? - As well as the inline definition option shown here, does it also work if the #:reader arg is a proc defined in one of the used modules? I guess it can't possibly work in the circular reference case -- i.e. where module A uses a reader defined in module B, but B also uses A and B was loaded first -- so this is probably deemed user error - but how is that error presented to the user? - Does it make sense to have both #:reader and #:use-syntax? Should we reimplement use-syntax as a special case of #:reader? Does it make sense that the places where your reader affects libguile (i.e. primitive-load) are different from the places where the module transformer affects libguile (i.e. the various versions of eval)? > 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))) Init value "read" here prevents your optimization in load.c from taking effect - so don't you want #f ? > 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); > + } I'm worried that this could reduce performance noticeably, and it seems unnecessarily inefficient. So ... <pause> ... Surely the low level concept here is that an alternative reader is a property of a port? In that case, I would expect that - the switch to the alternative reader would be implemented inside scm_read, using a new field on scm_t_port which can be set/read using set-port-reader!/port-reader - the module level #:reader option would be implemented by define-module calling set-port-reader! on current-load-port. (Note BTW that define-module should also do this when called to switch context to an already existing module.) Note that this also raises the question of what to do when someone types (define-module (module-with-reader)) at the REPL ... perhaps define-module should set the reader of the current input port also? > 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 Why 12? From the context I'd expect 5. Regards, Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader 2005-09-26 19:05 ` Neil Jerram @ 2005-09-27 8:21 ` Ludovic Courtès 2005-10-11 11:26 ` Ludovic Courtès 2005-10-19 22:56 ` [PATCH] Per-module reader Neil Jerram 0 siblings, 2 replies; 50+ messages in thread From: Ludovic Courtès @ 2005-09-27 8:21 UTC (permalink / raw) Cc: guile-devel Hi Neil, Thanks for this detailed analysis! Neil Jerram <neil@ossau.uklinux.net> writes: > This is nice; but concerns about whether it fits with transformer are: > > - Transformer is specified with #:use-syntax followed by module name, > which is a lot different from your syntax. I prefer your syntax, > because use-syntax requires the transformer procedure to have the > same name as the module it's defined in, which seems rubbish. But > on the other hand perhaps there is a reason for forcing the > reader/transformer to be defined in another module - are we missing > some subtlety here? First of all, I've always thought of the reader as something quite low-level, compared to macros. And I made the assumption that the transformer is something designed to implement macros. In fact, that is more or less what `boot-9.scm' says: - transformer: either #f or a function taking a scheme expression as delivered by read. If it is a function, it will be called to perform syntax transformations (e. g. makro expansion) on the given scheme expression. What I'm trying to address here is something that cannot be addressed using macros, nor by tweaking a module's transformer, precisely because the transformer only sees expressions returned by the reader. But I may be missing some subtlety, indeed. ;-) > - As well as the inline definition option shown here, does it also > work if the #:reader arg is a proc defined in one of the used > modules? I guess it can't possibly work in the circular reference > case -- i.e. where module A uses a reader defined in module B, but B > also uses A and B was loaded first -- so this is probably deemed > user error - but how is that error presented to the user? The `#:reader' argument must be a procedure either defined in the root module, or in one of the used modules declared in the `define-module' clause (it can't be a procedure defined in a subsequent `(use-modules ...)' form). As for circular dependencies, I think there's nothing special here: the problem is the same as for any other binding. > - Does it make sense to have both #:reader and #:use-syntax? Should > we reimplement use-syntax as a special case of #:reader? Does it > make sense that the places where your reader affects libguile > (i.e. primitive-load) are different from the places where the module > transformer affects libguile (i.e. the various versions of eval)? Yes, I think it makes sense. In some cases, a special reader and an appropriate transformer may both be used to solve the same problem (e.g. implementing the Elisp character syntax). However, the reader approach is lower-level and may be used to implement other things not implementable via a transformer (e.g. Elisp vectors, various keyword syntaxes, etc.). So I would say that it makes sense to keep both mechanisms side by side. >> 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))) > > Init value "read" here prevents your optimization in load.c from > taking effect - so don't you want #f ? Yes I do. :-) But it looked nicer and easier to understand to put `read' here. > I'm worried that this could reduce performance noticeably, and it > seems unnecessarily inefficient. So ... <pause> ... The two main sources of inefficiency are (i) the use of `scm_call' instead of a direct call to the reader subr, and (ii) the successive calls to `scm_current_module ()'. In the simple case, (i) can be avoided by having modules' reader default to `#f' as you noted earlier. As for (ii), we would greatly benefit from having an inlined version of `scm_current_module ()'. Anyway, given all the code that gets executed when reading from a file, I don't think this has a noticeable impact on performance. > Surely the low level concept here is that an alternative reader is a > property of a port? In that case, I would expect that > > - the switch to the alternative reader would be implemented inside > scm_read, using a new field on scm_t_port which can be set/read > using set-port-reader!/port-reader > > - the module level #:reader option would be implemented by > define-module calling set-port-reader! on current-load-port. (Note > BTW that define-module should also do this when called to switch > context to an already existing module.) Ports are lower-level abstractions and I think putting the notion of a reader into it would look odd. IMO, the reader option really belongs to modules, not ports. > Note that this also raises the question of what to do when someone > types (define-module (module-with-reader)) at the REPL ... perhaps > define-module should set the reader of the current input port also? You mean: `(define-module (module-with-reader) #:reader my-read)'? Well, that doesn't work because the REPL goes on using `read': guile> (define-module (hello) #:reader (lambda args (display "hello\n") (apply read args))) #<directory (hello) 30083450> guile> (+ 2 2) 4 However, this works fine: guile> (let ((real-read read)) (set! read (lambda args (display "hi!\n") (apply real-read args)))) guile> hi! (+ 2 2) 4 guile> hi! Conclusion: `define-module' should also set `read' to `(module-reader (current-module))'. This is a bug. >> 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 > > Why 12? From the context I'd expect 5. Why not? ;-) Because this has to be consistent with the field offsets of the `module-type' record type defined in `boot-9.scm'. Adding the `reader' field as the last one (offset 12) allows to maintain binary compatibility -- although I doubt there exists code that accesses the fields `duplicates-handlers', `observers', etc., from C given that there aren't even macros to do it. Thanks, Ludovic. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader 2005-09-27 8:21 ` Ludovic Courtès @ 2005-10-11 11:26 ` Ludovic Courtès 2005-10-11 23:24 ` Neil Jerram 2005-10-19 22:56 ` [PATCH] Per-module reader Neil Jerram 1 sibling, 1 reply; 50+ messages in thread From: Ludovic Courtès @ 2005-10-11 11:26 UTC (permalink / raw) Cc: guile-devel Hi, Let's not forget this thread (see <87hdc62a6c.fsf@laas.fr>), it's soooo interesting! Was my message so convincing that you don't know what to answer? ;-) Thanks, Ludovic. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader 2005-10-11 11:26 ` Ludovic Courtès @ 2005-10-11 23:24 ` Neil Jerram 2005-10-12 9:11 ` Ludovic Courtès 2005-10-17 9:17 ` [PATCH] Per-module reader, take #2 Ludovic Courtès 0 siblings, 2 replies; 50+ messages in thread From: Neil Jerram @ 2005-10-11 23:24 UTC (permalink / raw) ludovic.courtes@laas.fr (Ludovic Courtès) writes: > Hi, > > Let's not forget this thread (see <87hdc62a6c.fsf@laas.fr>), it's soooo > interesting! Was my message so convincing that you don't know what to > answer? ;-) I'll reply separately to some of the details in your other message, but overall I don't feel convinced that we need to support #:reader as a core module feature. If I'm understanding correctly, your argument rests on wanting to allow people to write a module like this: (define-module (shell utils) #:reader shell-reader #:use-module (shell reader) #:export (for)) for () { beg=$1 end=$2 ... } rather than like this (with the shell code in another file): (define-module (shell utils) #:use-module (shell reader) #:export (for)) (load-using-reader "for.sh" shell-reader) I admit that in the future something like this _could_ be a key part of Guile's support for translators, but right now we don't have enough translation experience to say that this will end up being the right thing, and on its own merits the benefit of being able to write foreign code with a Guile module header in the same file seems very marginal to me. And to get this marginal benefit we have to add a module option and some code which will slow down normal operation. Not noticeably perhaps, but it all adds up. Finally, wouldn't you be making more headache for yourself (in the medium term) by relying on #:reader in the core rather than something like load-using-reader in your library? With #:reader in the core, your package code would only work with Guile CVS and >=1.7 releases after a certain date, whereas with load-using-reader your code will work with 1.6, 1.7/1.8 and probably 1.4 as well. Sorry to push back so much, but that's my view. Regards, Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader 2005-10-11 23:24 ` Neil Jerram @ 2005-10-12 9:11 ` Ludovic Courtès 2005-10-17 9:17 ` [PATCH] Per-module reader, take #2 Ludovic Courtès 1 sibling, 0 replies; 50+ messages in thread From: Ludovic Courtès @ 2005-10-12 9:11 UTC (permalink / raw) Cc: guile-devel Neil Jerram <neil@ossau.uklinux.net> writes: > If I'm understanding correctly, your argument rests on wanting to > allow people to write a module like this: > > (define-module (shell utils) > #:reader shell-reader > #:use-module (shell reader) > #:export (for)) > > for () { > beg=$1 > end=$2 > ... > } > > rather than like this (with the shell code in another file): > > (define-module (shell utils) > #:use-module (shell reader) > #:export (for)) > > (load-using-reader "for.sh" shell-reader) That could be one possibility. The other issue is providing a basic mechanism to help fixing the current single-instance `read' issue. Again, there's only one instance of `read', and `read-enable', `read-hash-extend' and the likes modify that very single instance. This means that they have side-effects /across/ modules. This also means that it may turn out that two modules cannot be used together because they rely on incompatible reader settings. Maybe you do not consider this to be an issue in practice, but at least, I think we'd agree that this approach is flawed. Assuming that this /is/ an issue in practice, I can think of only two ways to fix this: 1. Remove all the `read' configuration tricks; 2. Allow for per-module readers. Obviously, (1) is not acceptable to me, and I guess, for most people. Part of (2) also means being able to instantiate and tweak readers, which is what `guile-reader' is about. > I admit that in the future something like this _could_ be a key part > of Guile's support for translators, but right now we don't have enough > translation experience to say that this will end up being the right > thing, and on its own merits the benefit of being able to write > foreign code with a Guile module header in the same file seems very > marginal to me. I was not thinking about such extreme uses of the system. And honestly, I doubt Guile will ever be able to run foreign code. It might have been able to achieve this in its glory days back in 1999-2000, but I don't think it should be a goal now. This is sad, especially since you apparently did a great job with Elisp translation. > And to get this marginal benefit we have to add a module option and > some code which will slow down normal operation. Not noticeably > perhaps, but it all adds up. Not noticeably, indeed. And modules are read only once. And Guile is an interpreter anyway. ;-) However, in my previous post, I noted: The two main sources of inefficiency are (i) the use of `scm_call' instead of a direct call to the reader subr, and (ii) the successive calls to `scm_current_module ()'. In the simple case, (i) can be avoided by having modules' reader default to `#f' as you noted earlier. As for (ii), we would greatly benefit from having an inlined version of `scm_current_module ()'. Both optimizations seem feasible. > Finally, wouldn't you be making more headache for yourself (in the > medium term) by relying on #:reader in the core rather than something > like load-using-reader in your library? With #:reader in the core, > your package code would only work with Guile CVS and >=1.7 releases > after a certain date, whereas with load-using-reader your code will > work with 1.6, 1.7/1.8 and probably 1.4 as well. Of course I can do without it. The point is that I considered this to be an elegant solution to allow coexistence within a program of different syntax *variants* (personally, I don't care about writing Guile modules in Python or Sh, etc.). Thanks, Ludovic. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #2 2005-10-11 23:24 ` Neil Jerram 2005-10-12 9:11 ` Ludovic Courtès @ 2005-10-17 9:17 ` Ludovic Courtès 2005-10-17 20:41 ` Neil Jerram 1 sibling, 1 reply; 50+ messages in thread From: Ludovic Courtès @ 2005-10-17 9:17 UTC (permalink / raw) Cc: guile-devel Hi, Neil Jerram <neil@ossau.uklinux.net> writes: > And to get this marginal benefit we have to add a module option and > some code which will slow down normal operation. Not noticeably > perhaps, but it all adds up. Following your concern (I mean the performance concern, not the "marginal benefit" concern), I thought of another way to achieve the same thing, a bit more generic and slightly better performance-wise (patch attached). The idea is to use a fluid to store the current reader. `primitive-load' can look at the value of this fluid to know what the current reader is. When a file is loaded, it can modify the current reader. Once it's been loaded, its value is restored back to the original (not unlike `current-module'...). To illustrate this, suppose a file that does this: (set-current-reader (lambda args (format #t "hello~%") (apply read args))) (+ 2 3) Here is what happens when it's loaded: $ guile guile> (+ 2 2) 4 guile> (load "paf.scm") hello hello guile> (+ 2 2) 4 guile> Now, `define-module' can use the very same mechanism to implement per-module readers. In terms of performance, fetching the current reader (as done in `primitive-load') boils down to a function call (to `scm_i_fast_fluid_ref ()') which itself is pretty fast (a couple of pointer dereferences, roughly). But of course, this still more costly than nothing. What do you think? Thanks, Ludovic. --- orig/ice-9/boot-9.scm +++ mod/ice-9/boot-9.scm @@ -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,9 @@ uses binder #f #f #f #f #f #f '() (make-weak-value-hash-table 31) - 0))) + 0 + #f ;; the default reader + ))) ;; 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 +1250,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 +2047,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 +2155,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} @@ -2538,7 +2555,7 @@ (display prompt) (force-output) (run-hook before-read-hook) - (read (current-input-port)))) + ((or (current-reader) read) (current-input-port)))) (define (scm-style-repl) @@ -2851,6 +2868,7 @@ (let ((m (process-define-module (list ,@(compile-define-module-args args))))) (set-current-module m) + (set-current-reader (module-reader m)) m)) (else (error "define-module can only be used at the top level")))) --- orig/libguile/load.c +++ mod/libguile/load.c @@ -42,6 +42,7 @@ #include "libguile/validate.h" #include "libguile/load.h" +#include "libguile/fluids.h" #include <sys/types.h> #include <sys/stat.h> @@ -55,13 +56,59 @@ #endif \f +/* The current reader (a fluid). */ + +static SCM the_reader = SCM_BOOL_F; +static size_t the_reader_fluid_num = 0; + +#define CURRENT_READER() SCM_FAST_FLUID_REF (the_reader_fluid_num) +#define SET_CURRENT_READER(_val) \ +do \ +{ \ + SCM_FAST_FLUID_SET_X (the_reader_fluid_num, (_val)); \ +} \ +while (0) + + +SCM_DEFINE (scm_current_reader, "current-reader", 0, 0, 0, + (void), + "Return the current reader.") +#define FUNC_NAME s_scm_current_reader +{ + return CURRENT_READER (); +} +#undef FUNC_NAME + +SCM_DEFINE (scm_set_current_reader, "set-current-reader", 1, 0, 0, + (SCM reader), + "Set the current reader to @var{reader} and return the " + "previous current reader.") +#define FUNC_NAME s_scm_set_current_reader +{ + SCM previous; + + /* The value `#f' is a special allowed value for READER which means ``use + Guile's built-in reader''. See how `primitive-load' uses it as an + optimization. */ + if (reader != SCM_BOOL_F) + SCM_VALIDATE_PROC (1, reader); + + previous = CURRENT_READER (); + SET_CURRENT_READER (reader); + + return previous; +} +#undef FUNC_NAME + + +\f /* Loading a file, given an absolute filename. */ /* Hook to run when we load a file, perhaps to announce the fact somewhere. Applied to the full name of the file. */ static SCM *scm_loc_load_hook; -SCM_DEFINE (scm_primitive_load, "primitive-load", 1, 0, 0, +SCM_DEFINE (scm_primitive_load, "primitive-load", 1, 0, 0, (SCM filename), "Load the file named @var{filename} and evaluate its contents in\n" "the top-level environment. The load paths are not searched;\n" @@ -86,11 +133,23 @@ scm_frame_begin (SCM_F_FRAME_REWINDABLE); scm_i_frame_current_load_port (port); + /* Make `current-reader' local to this frame's dynamic extent. */ + scm_frame_fluid (the_reader, CURRENT_READER ()); + while (1) { - SCM form = scm_read (port); + SCM reader, form; + + reader = CURRENT_READER (); + + 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); } @@ -501,6 +560,10 @@ scm_nullstr))); scm_loc_load_hook = SCM_VARIABLE_LOC (scm_c_define ("%load-hook", SCM_BOOL_F)); + the_reader = scm_permanent_object (scm_make_fluid ()); + the_reader_fluid_num = SCM_FLUID_NUM (the_reader); + SET_CURRENT_READER (SCM_BOOL_F); + init_build_info (); #include "libguile/load.x" --- orig/libguile/load.h +++ mod/libguile/load.h @@ -38,6 +38,9 @@ SCM_API SCM scm_c_primitive_load_path (const char *filename); SCM_API void scm_init_load (void); +SCM_API SCM scm_current_reader (void); +SCM_API SCM scm_set_current_reader (SCM reader); + #endif /* SCM_LOAD_H */ /* --- orig/libguile/modules.h +++ mod/libguile/modules.h @@ -45,6 +45,7 @@ #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_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 ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #2 2005-10-17 9:17 ` [PATCH] Per-module reader, take #2 Ludovic Courtès @ 2005-10-17 20:41 ` Neil Jerram 2005-10-18 7:42 ` Ludovic Courtès 0 siblings, 1 reply; 50+ messages in thread From: Neil Jerram @ 2005-10-17 20:41 UTC (permalink / raw) ludovic.courtes@laas.fr (Ludovic Courtès) writes: > Following your concern (I mean the performance concern, not the > "marginal benefit" concern), I thought of another way to achieve the > same thing, a bit more generic and slightly better performance-wise > (patch attached). [...] Thanks for taking my considerations into account and producing this update. My gut feel is that I do like this new patch better, but I'd like to think about it more. I also need to go back and finish my draft reply to your previous email - I'll try to do that in the next day or so. Also, do you have docs for guile-reader up somewhere? Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #2 2005-10-17 20:41 ` Neil Jerram @ 2005-10-18 7:42 ` Ludovic Courtès 2005-10-19 22:23 ` Neil Jerram 0 siblings, 1 reply; 50+ messages in thread From: Ludovic Courtès @ 2005-10-18 7:42 UTC (permalink / raw) Cc: guile-devel Hi Neil, Neil Jerram <neil@ossau.uklinux.net> writes: > Thanks for taking my considerations into account and producing this > update. My gut feel is that I do like this new patch better, but I'd > like to think about it more. I also need to go back and finish my > draft reply to your previous email - I'll try to do that in the next > day or so. Ok. > Also, do you have docs for guile-reader up somewhere? Yes. The doc for 0.1 is there: http://www.laas.fr/~lcourtes/software/guile/guile-reader.html It's still changing but I think the basic ideas are there. I'd be really glad to hear comments about this. In fact, I already fixed small deficiencies in the API which I only encountered as I was actually trying to build uncommon readers. Oh, and I set up a project on Savannah to keep track of this and there's even a mailing list: http://savannah.nongnu.org/projects/guile-reader/ Thanks, Ludovic. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #2 2005-10-18 7:42 ` Ludovic Courtès @ 2005-10-19 22:23 ` Neil Jerram 2005-10-20 1:22 ` Kevin Ryde 2005-10-20 7:48 ` Ludovic Courtès 0 siblings, 2 replies; 50+ messages in thread From: Neil Jerram @ 2005-10-19 22:23 UTC (permalink / raw) ludovic.courtes@laas.fr (Ludovic Courtès) writes: > Neil Jerram <neil@ossau.uklinux.net> writes: > >> Thanks for taking my considerations into account and producing this >> update. My gut feel is that I do like this new patch better, but I'd >> like to think about it more. I also need to go back and finish my >> draft reply to your previous email - I'll try to do that in the next >> day or so. > > Ok. > >> Also, do you have docs for guile-reader up somewhere? > > Yes. The doc for 0.1 is there: > > http://www.laas.fr/~lcourtes/software/guile/guile-reader.html Thanks, very interesting. I have some queries about your API, but I'll leave those for another time. I've finally reached a clear view on what I think about your reader patch. I completely agree with your arguments as regards what is problematic about the current system of read-hash-extend and read options, and I think it's great that you are using guile-reader to try to solve that. (And the GNU Lightning aspect, which I don't understand yet, sounds very cool.) I don't think it should be connected with modules, though. In my view: - modules should be about identifier access and visibility (including issues such as possible separate compilation in future), and nothing else (and yes, this does imply that #:use-syntax was a mistake) - the appropriate unit of scope for your custom readers should be the file, not the module; for two reasons in particular: - the file makes sense as a unit within which the coder would want custom reading rules - associating a reader with a file instead of with a module means that your whole enhancement will work for code that is not organized into a module, as well as for that which is! What do you think? If you agree, I think the implication is that two APIs (which can probably be straightforward procedures) would be useful: 1. A way to say "change the reader to XXX for the rest of this file". 2. A way to say "load FILE using reader XXX". Regards, Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #2 2005-10-19 22:23 ` Neil Jerram @ 2005-10-20 1:22 ` Kevin Ryde 2005-10-20 7:59 ` Ludovic Courtès 2005-10-20 7:48 ` Ludovic Courtès 1 sibling, 1 reply; 50+ messages in thread From: Kevin Ryde @ 2005-10-20 1:22 UTC (permalink / raw) Cc: guile-devel Neil Jerram <neil@ossau.uklinux.net> writes: > > 1. A way to say "change the reader to XXX for the rest of this file". I think that may be possible already using current-load-port. Something like (define-module (foo bar) ...) (my-zany-reader) where `my-zany-reader' reads and parses from current-load-port and does whatever with the results, like make new defines presumably. This could be used for the entire rest of the file, or stop at some point like a "here-document" perhaps. Wouldn't be compiler-friendly, but I wouldn't worry about that until there's an actual compiler to be friendly with :-). > 2. A way to say "load FILE using reader XXX". `load' is pretty simple, isn't it? One can make a new open/read/eval without too much trouble. I guess there's bits like path searching and current module saving. Maybe they only need to be better documented though. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #2 2005-10-20 1:22 ` Kevin Ryde @ 2005-10-20 7:59 ` Ludovic Courtès 2005-10-20 19:30 ` Kevin Ryde 0 siblings, 1 reply; 50+ messages in thread From: Ludovic Courtès @ 2005-10-20 7:59 UTC (permalink / raw) Cc: guile-devel Hi, Kevin Ryde <user42@zip.com.au> writes: > I think that may be possible already using current-load-port. > Something like > > (define-module (foo bar) > ...) > (my-zany-reader) > > where `my-zany-reader' reads and parses from current-load-port and > does whatever with the results, like make new defines presumably. > > This could be used for the entire rest of the file, or stop at some > point like a "here-document" perhaps. This looks quite hackish, indeed. And what exactly would happen to `primitive-load' (which is the one that triggered the call to `my-zany-reader') when `my-zany-reader' returns? If everything works fine, then the file offset of `current-load-port' will now point to where `my-zany-reader' finished its job. That's relying too much on side-effects. > Wouldn't be compiler-friendly, but I wouldn't worry about that until > there's an actual compiler to be friendly with :-). Well, keep in mind that Keishude's Guile-VM is not that far from usable. So far, I only ported it to 1.7 and started using it and documenting it. There are certainly still bugs but it's worth putting some efforts in it. I hope I'll be able to release something in the foreseeable future. > `load' is pretty simple, isn't it? One can make a new open/read/eval > without too much trouble. I guess there's bits like path searching > and current module saving. Maybe they only need to be better > documented though. Yes, they probably do need to be better documented. ;-) Thanks, Ludovic. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #2 2005-10-20 7:59 ` Ludovic Courtès @ 2005-10-20 19:30 ` Kevin Ryde 2005-10-20 21:27 ` Neil Jerram 0 siblings, 1 reply; 50+ messages in thread From: Kevin Ryde @ 2005-10-20 19:30 UTC (permalink / raw) Cc: guile-devel ludovic.courtes@laas.fr (Ludovic Courtès) writes: > > And what exactly would happen to > `primitive-load' (which is the one that triggered the call to > `my-zany-reader') when `my-zany-reader' returns? It sees eof, and stops. Or it sees the rest of the file if the new reader only takes an inlined middle bit of special syntax. A nested parser like that seems pretty clean and pretty normal to me. I think it can do almost everything you're aiming for. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #2 2005-10-20 19:30 ` Kevin Ryde @ 2005-10-20 21:27 ` Neil Jerram 0 siblings, 0 replies; 50+ messages in thread From: Neil Jerram @ 2005-10-20 21:27 UTC (permalink / raw) Kevin Ryde <user42@zip.com.au> writes: > ludovic.courtes@laas.fr (Ludovic Courtès) writes: >> >> And what exactly would happen to >> `primitive-load' (which is the one that triggered the call to >> `my-zany-reader') when `my-zany-reader' returns? > > It sees eof, and stops. Or it sees the rest of the file if the new > reader only takes an inlined middle bit of special syntax. A nested > parser like that seems pretty clean and pretty normal to me. I think > it can do almost everything you're aiming for. I think Kevin is right that this is possible and would work, but there is also some merit in the arguments that - even if it is possible, emulating/duplicating the primitive-load loop is a bit dull - in future the primitive-load loop might acquire more features, and it would be nice if those features Just Worked for Ludovic's readers also. On the second point there's a specific feature that I have in mind, namely being able to set previously specified breakpoints on each expression as soon as it has been read, and before it is evaluated, so I'm not just speculating wildly. So I think the fluid current reader approach is quite nice, as long as we are happy that it doesn't introduce any significant performance overhead. Regards, Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #2 2005-10-19 22:23 ` Neil Jerram 2005-10-20 1:22 ` Kevin Ryde @ 2005-10-20 7:48 ` Ludovic Courtès 2005-10-20 10:52 ` Tomas Zerolo 2005-10-20 22:09 ` Neil Jerram 1 sibling, 2 replies; 50+ messages in thread From: Ludovic Courtès @ 2005-10-20 7:48 UTC (permalink / raw) Cc: guile-devel Hi Neil, Neil Jerram <neil@ossau.uklinux.net> writes: > I don't think it should be connected with modules, though. In my > view: > > - modules should be about identifier access and visibility (including > issues such as possible separate compilation in future), and nothing > else (and yes, this does imply that #:use-syntax was a mistake) Right. > - the appropriate unit of scope for your custom readers should be the > file, not the module; for two reasons in particular: This makes sense, too. > - the file makes sense as a unit within which the coder would want > custom reading rules > > - associating a reader with a file instead of with a module means > that your whole enhancement will work for code that is not > organized into a module, as well as for that which is! Well, yes, this makes sense. > What do you think? If you agree, I think the implication is that two > APIs (which can probably be straightforward procedures) would be > useful: > > 1. A way to say "change the reader to XXX for the rest of this file". I believe `set-current-reader' (introduced in the second patch) can do this job pretty well. What do you think? > 2. A way to say "load FILE using reader XXX". This is not really an issue since one can always write their own `load-with-reader' procedure. Of course, we could also provide one with Guile (like `primitive-load-with-reader') taking a reader as a second argument. Thanks for your comments! Ludovic. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #2 2005-10-20 7:48 ` Ludovic Courtès @ 2005-10-20 10:52 ` Tomas Zerolo 2005-10-20 14:42 ` Ludovic Courtès 2005-10-20 22:09 ` Neil Jerram 1 sibling, 1 reply; 50+ messages in thread From: Tomas Zerolo @ 2005-10-20 10:52 UTC (permalink / raw) [-- Attachment #1.1: Type: text/plain, Size: 958 bytes --] On Thu, Oct 20, 2005 at 09:48:50AM +0200, Ludovic Court?s wrote: > Hi Neil, > > Neil Jerram <neil@ossau.uklinux.net> writes: > > > I don't think it should be connected with modules, though. In my > > view: > > > > - modules should be about identifier access and visibility (including > > issues such as possible separate compilation in future), and nothing > > else (and yes, this does imply that #:use-syntax was a mistake) > > Right. > > > - the appropriate unit of scope for your custom readers should be the > > file, not the module; for two reasons in particular: > > This makes sense, too. [snip] But don't we loose the possibility then to have ``embedded goo´´ (say, for example, something like a snippet of SQL in an otherwise Scheme file)? This would be, I think, one of the nifty uses for pluggable readers... May be I'm completely off-base, since quite swamped ATM. If so, ignore. Thanks -- tomás [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] [-- Attachment #2: Type: text/plain, Size: 143 bytes --] _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #2 2005-10-20 10:52 ` Tomas Zerolo @ 2005-10-20 14:42 ` Ludovic Courtès 0 siblings, 0 replies; 50+ messages in thread From: Ludovic Courtès @ 2005-10-20 14:42 UTC (permalink / raw) Cc: guile-devel, Neil Jerram Hi, tomas@tuxteam.de (Tomas Zerolo) writes: > But don't we loose the possibility then to have ``embedded goo´´ (say, > for example, something like a snippet of SQL in an otherwise Scheme > file)? This would be, I think, one of the nifty uses for pluggable > readers... [It looks like something fishy happened with your mailer...] No, we don't lose anything by having a mechanism for per-file readers rather than per-module readers. In fact, the latter can be emulated on top of the former. In fact, `set-current-reader' allows for better than per-file reader: you can switch back and forth readers from within a file that is being loaded. BTW, for SQL requests, you'd certainly better use `read-hash-extend' for instance. I see custom readers as a way to choose among various syntax variants for the *Scheme* language (or close relatives). Thanks, Ludovic. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #2 2005-10-20 7:48 ` Ludovic Courtès 2005-10-20 10:52 ` Tomas Zerolo @ 2005-10-20 22:09 ` Neil Jerram 2005-10-21 7:43 ` Ludovic Courtès 1 sibling, 1 reply; 50+ messages in thread From: Neil Jerram @ 2005-10-20 22:09 UTC (permalink / raw) ludovic.courtes@laas.fr (Ludovic Courtès) writes: > Hi Neil, > > Neil Jerram <neil@ossau.uklinux.net> writes: > >> 1. A way to say "change the reader to XXX for the rest of this file". > > I believe `set-current-reader' (introduced in the second patch) can do > this job pretty well. What do you think? Yes, indeed. Just one detail: I suspect that scm_frame_fluid(the_reader, SCM_BOOL_F); might be less surprising than scm_frame_fluid(the_reader, CURRENT_READER()); at the start of primitive-load. Given how Guile works already, I think it's more natural for files to be independent of each other, reader-wise, and that we add something new that people can use to get reader inheritance when they want that. (`include' feels like a nice name to me. It could be implemented using an optional reader arg to load/primitive-load, something like: (include FILE) -> (load FILE (current-reader)) And then primitive-load would call scm_frame_fluid with the optional arg if supplied, SCM_BOOL_F otherwise.) >> 2. A way to say "load FILE using reader XXX". > > This is not really an issue since one can always write their own > `load-with-reader' procedure. Of course, we could also provide one with > Guile (like `primitive-load-with-reader') taking a reader as a second > argument. Yes. I think this _is_ worth doing, for the same reasons as in my followup to Kevin's email. Regards, Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #2 2005-10-20 22:09 ` Neil Jerram @ 2005-10-21 7:43 ` Ludovic Courtès 2005-10-24 11:43 ` Ludovic Courtès 2005-10-28 21:26 ` Neil Jerram 0 siblings, 2 replies; 50+ messages in thread From: Ludovic Courtès @ 2005-10-21 7:43 UTC (permalink / raw) Cc: guile-devel Hi, Neil Jerram <neil@ossau.uklinux.net> writes: > Yes, indeed. Just one detail: I suspect that > > scm_frame_fluid(the_reader, SCM_BOOL_F); > > might be less surprising than > > scm_frame_fluid(the_reader, CURRENT_READER()); > > at the start of primitive-load. Given how Guile works already, I > think it's more natural for files to be independent of each other, > reader-wise, and that we add something new that people can use to get > reader inheritance when they want that. Right. I did hesitate between the two solutions in fact. I was thinking that one might want to purposefully call `set-current-reader' just before invoking `primitive-load'. But in fact, for that purpose, we'd better provide a `load-with-reader' procedure as you said. And it is true that having `current-reader' default to `#f' would keep away users from experiencing weird unexpected behavior. > (`include' feels like a nice name to me. It could be implemented > using an optional reader arg to load/primitive-load, something like: > > (include FILE) -> (load FILE (current-reader)) Maybe `load-with-reader' is more explicit, while not as nice? ;-) > And then primitive-load would call scm_frame_fluid with the optional > arg if supplied, SCM_BOOL_F otherwise.) In fact, in order to retain binary compatibility, we'd have to provide another function which would essentially contain the same code as `primitive-load' except for the optional reader argument and the default value of the `current-reader' fluid. I'll try to have an attempt at implementing it today. Thanks, Ludovic. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #2 2005-10-21 7:43 ` Ludovic Courtès @ 2005-10-24 11:43 ` Ludovic Courtès 2005-10-28 21:26 ` Neil Jerram 1 sibling, 0 replies; 50+ messages in thread From: Ludovic Courtès @ 2005-10-24 11:43 UTC (permalink / raw) Cc: guile-devel Hi, Recently, Neil and I agreed that the reader setting should be thought of as per-file instead of per-module. Happily, the second patch I sent implements per-file readers (which may be set via `set-current-reader') while maintaining the per-module reader mechanism (via `(define-module (m) :reader r)', implemented on top of `set-current-reader'). I'm actually unsure whether we really want to get rid of the `#:reader' option to `define-module'. Although the same effects can be achieved with `set-current-reader', it provides an alternative and IMO clearer way to achieve this. What do you think? Thanks, Ludovic. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #2 2005-10-21 7:43 ` Ludovic Courtès 2005-10-24 11:43 ` Ludovic Courtès @ 2005-10-28 21:26 ` Neil Jerram 2005-10-28 22:38 ` Kevin Ryde 1 sibling, 1 reply; 50+ messages in thread From: Neil Jerram @ 2005-10-28 21:26 UTC (permalink / raw) ludovic.courtes@laas.fr (Ludovic Courtès) writes: >> (`include' feels like a nice name to me. It could be implemented >> using an optional reader arg to load/primitive-load, something like: >> >> (include FILE) -> (load FILE (current-reader)) > > Maybe `load-with-reader' is more explicit, while not as nice? ;-) My idea of `include' would map to `load-with-current-reader', not to `load-with-reader'. I would expect `load-with-reader' to require an explicit reader argument. We're into pretty fine details here, though! I don't mind that much either way. >> And then primitive-load would call scm_frame_fluid with the optional >> arg if supplied, SCM_BOOL_F otherwise.) > > In fact, in order to retain binary compatibility, we'd have to provide > another function which would essentially contain the same code as > `primitive-load' except for the optional reader argument and the default > value of the `current-reader' fluid. Is binary compatibility a requirement? I presume this is aimed for 1.8, and presumably for 1.8 we'd bump libguile's major version, wouldn't we? (Getting into territory I don't really understand ...) Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #2 2005-10-28 21:26 ` Neil Jerram @ 2005-10-28 22:38 ` Kevin Ryde 2005-10-29 8:58 ` Neil Jerram 0 siblings, 1 reply; 50+ messages in thread From: Kevin Ryde @ 2005-10-28 22:38 UTC (permalink / raw) Neil Jerram <neil@ossau.uklinux.net> writes: > > Is binary compatibility a requirement? I presume this is aimed for > 1.8, and presumably for 1.8 we'd bump libguile's major version, > wouldn't we? (Getting into territory I don't really understand ...) Adding an arg to scm_primitive_load (if that's the question here), would be very bad, since that function is described in the manual. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #2 2005-10-28 22:38 ` Kevin Ryde @ 2005-10-29 8:58 ` Neil Jerram 2005-10-30 19:55 ` Neil Jerram 0 siblings, 1 reply; 50+ messages in thread From: Neil Jerram @ 2005-10-29 8:58 UTC (permalink / raw) Kevin Ryde <user42@zip.com.au> writes: > Adding an arg to scm_primitive_load (if that's the question here), > would be very bad, since that function is described in the manual. Good point. I think my statement stands that binary compatibility is not required, but adding an arg to scm_primitive_load would break both binary and source compatibility, and we _do_ want to preserve source compatibility. So yes, the signature of scm_primitive_load has to stay as it is. That doesn't mean we have to duplicate code, though. We could move the code into scm_primitive_load_with_reader, and change scm_primitive_load to call that. Another detail that needs thought is whether any of the stack of load procedures defined in r4rs.scm and boot-9.scm (load-from-path, load and load-module) need enhancing to take a reader arg. Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #2 2005-10-29 8:58 ` Neil Jerram @ 2005-10-30 19:55 ` Neil Jerram 2005-11-07 16:06 ` [PATCH] Per-module reader, take #3 Ludovic Courtès 0 siblings, 1 reply; 50+ messages in thread From: Neil Jerram @ 2005-10-30 19:55 UTC (permalink / raw) Neil Jerram <neil@ossau.uklinux.net> writes: > Another detail that needs thought is whether any of the stack of load > procedures defined in r4rs.scm and boot-9.scm (load-from-path, load > and load-module) need enhancing to take a reader arg. The stack of load procedures is... primitive-load, defined in load.c `load' defined in r4rs.scm, which boot-9.scm then renames as `basic-load'. This is presumably intended to be an R4RS-compliant load; its implementation builds on primitive-load by setting a hook which can announce the file being loaded, and by starting a new stack (start-stack). `load-module' defined in boot-9.scm. This builds on basic-load by adding - save-module-excursion, so that loading a module doesn't change the loader's current module - the ability to load files with relative path names. Finally boot-9 does (define load load-module), so `load' ends up being what I just described as load-module. So one possibility for adding custom reader support to all this is... - Don't put any current-reader framing code in primitive-load. In other words, don't reset current-reader to #f (or anything else) at the start of primitive-load, and don't use framing to restore the value of the current-reader at the end if the loaded code has changed it. This means that primitive-load keeps its existing primitiveness - i.e. it isn't much more than just a read eval loop. - Add an optional reader arg to both r4rs's load and boot-9's load-module, and treat as #f if not specified. In r4rs load, do (with-fluids ((the-reader reader)) ...) around the existing code. In load-module, just pass the reader through to basic-load. This would preserve existing behaviour for any calls to load or use-modules, which are the mainline cases, even when the caller has installed a non-default reader, but it also allows developers to achieve different behaviour when they want it by using primitive-load and the optional reader arg to load. This can also be seen as analogous to how primitive-eval allows (current-module) to change, but eval doesn't. Regards, Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-10-30 19:55 ` Neil Jerram @ 2005-11-07 16:06 ` Ludovic Courtès 2005-11-16 21:13 ` Neil Jerram 0 siblings, 1 reply; 50+ messages in thread From: Ludovic Courtès @ 2005-11-07 16:06 UTC (permalink / raw) Cc: guile-devel Hi Neil, Thanks for your detailed analysis of the `load' procedure stack. Neil Jerram <neil@ossau.uklinux.net> writes: > So one possibility for adding custom reader support to all this is... > > - Don't put any current-reader framing code in primitive-load. In > other words, don't reset current-reader to #f (or anything else) at > the start of primitive-load, and don't use framing to restore the > value of the current-reader at the end if the loaded code has > changed it. This means that primitive-load keeps its existing > primitiveness - i.e. it isn't much more than just a read eval loop. > > - Add an optional reader arg to both r4rs's load and boot-9's > load-module, and treat as #f if not specified. In r4rs load, do > (with-fluids ((the-reader reader)) ...) around the existing code. In > load-module, just pass the reader through to basic-load. > > This would preserve existing behaviour for any calls to load or > use-modules, which are the mainline cases, even when the caller has > installed a non-default reader, but it also allows developers to > achieve different behaviour when they want it by using primitive-load > and the optional reader arg to load. Agreed, this approach is consistent with the current `load' stack. The patch below does what you described. I left the `#:reader' option to `define-module' as an alternative, higher-level approach to choosing an alternate reader. Please let me know what you think about it. And sorry for consuming so much of your time! ;-) Thanks, Ludovic. PS: I can prepare ChangeLog entries if it looks good to commit. --- orig/doc/ref/api-evaluation.texi +++ mod/doc/ref/api-evaluation.texi @@ -409,12 +409,21 @@ @subsection Loading Scheme Code from File @rnindex load -@deffn {Scheme Procedure} load filename +@deffn {Scheme Procedure} load filename [reader] Load @var{filename} and evaluate its contents in the top-level -environment. The load paths are not searched. If the variable -@code{%load-hook} is defined, it should be bound to a procedure that -will be called before any code is loaded. See documentation for -@code{%load-hook} later in this section. +environment. The load paths are not searched. If @var{reader} is +provided, then it should be either @code{#f}, in which case the +built-in @code{read} procedure (@pxref{Scheme Read}) is used to load +the file, or a reader procedure to use when reading data from file +@var{filename}. Such a reader procedure must work like @code{read} +(@pxref{Scheme Read}). + +The Scheme code in file @var{filename} may change the reader procedure +used by @code{load} using @code{set-current-reader} (see below). + +If the variable @code{%load-hook} is defined, it should be bound to a +procedure that will be called before any code is loaded. See +documentation for @code{%load-hook} later in this section. @end deffn @deffn {Scheme Procedure} load-from-path filename @@ -431,6 +440,8 @@ @code{%load-hook} is defined, it should be bound to a procedure that will be called before any code is loaded. See the documentation for @code{%load-hook} later in this section. +The reader procedure used to read the file named @var{filename} is the +one specified using @code{set-current-reader} (see below). @end deffn @deffn {Scheme Procedure} primitive-load-path filename @@ -475,6 +486,23 @@ The load port is used internally by @code{primitive-load}. @end deffn +@deffn {Scheme Procedure} current-reader +@deffnx {C Function} scm_current_reader () +Return the reader procedure used by @code{primitive-load} (and +@code{load}) during the dynamic extent of the current frame (see +@xref{Dynamic Wind}, and @pxref{Frames}). +@end deffn + +@deffn {Scheme Procedure} set-current-reader reader +@deffnx {C Function} scm_set_current_reader (reader) +During the dynamic extent of the current frame, set the reader +procedure used by @code{primitive-load} (and @code{load}) to +@var{reader}. If @var{reader} is a procedure, is must follow the +interface of @code{read} (@pxref{Scheme Read}). If @var{reader} is +@code{#f}, it is assumed that Guile's built-in @code{read} procedure +will be used. +@end deffn + @defvar %load-extensions A list of default file extensions for files containing Scheme code. @code{%search-load-path} tries each of these extensions when looking for --- orig/ice-9/boot-9.scm +++ mod/ice-9/boot-9.scm @@ -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,9 @@ uses binder #f #f #f #f #f #f '() (make-weak-value-hash-table 31) - 0))) + 0 + #f ;; the default reader + ))) ;; 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 +1250,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! @@ -1633,19 +1638,28 @@ (set-current-module outer-module) (set! outer-module #f))))) +;; Rename R4RS' `load'. (define basic-load load) -(define (load-module filename) +(define (load-module filename . reader) (save-module-excursion (lambda () (let ((oldname (and (current-load-port) - (port-filename (current-load-port))))) + (port-filename (current-load-port)))) + (reader (if (null? reader) + #f + (if (null? (cdr reader)) + (car reader) + (scm-error 'wrong-number-of-args "load-module" + "too many arguments: ~A" + (list reader) #f))))) (basic-load (if (and oldname (> (string-length filename) 0) (not (char=? (string-ref filename 0) #\/)) (not (string=? (dirname oldname) "."))) (string-append (dirname oldname) "/" filename) - filename)))))) + filename) + reader))))) \f @@ -2042,10 +2056,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 +2164,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} @@ -2538,7 +2564,7 @@ (display prompt) (force-output) (run-hook before-read-hook) - (read (current-input-port)))) + ((or (current-reader) read) (current-input-port)))) (define (scm-style-repl) @@ -2851,6 +2877,7 @@ (let ((m (process-define-module (list ,@(compile-define-module-args args))))) (set-current-module m) + (set-current-reader (module-reader m)) m)) (else (error "define-module can only be used at the top level")))) --- orig/ice-9/r4rs.scm +++ mod/ice-9/r4rs.scm @@ -206,6 +206,19 @@ (set! %load-hook %load-announce) -(define (load name) - (start-stack 'load-stack - (primitive-load name))) +(define (load name . reader) + (let ((previous-reader (current-reader)) + (reader (if (null? reader) + #f ;; use the built-in reader + (if (null? (cdr reader)) + (car reader) + (scm-error 'wrong-number-of-args "load-module" + "too many arguments: ~A" + (list reader) #f))))) + (dynamic-wind + (lambda () (set-current-reader reader)) + (lambda () + (start-stack 'load-stack + (primitive-load name))) + (lambda () (set-current-reader previous-reader))))) + --- orig/libguile/load.c +++ mod/libguile/load.c @@ -42,6 +42,7 @@ #include "libguile/validate.h" #include "libguile/load.h" +#include "libguile/fluids.h" #include <sys/types.h> #include <sys/stat.h> @@ -55,13 +56,59 @@ #endif \f +/* The current reader (a fluid). */ + +static SCM the_reader = SCM_BOOL_F; +static size_t the_reader_fluid_num = 0; + +#define CURRENT_READER() SCM_FAST_FLUID_REF (the_reader_fluid_num) +#define SET_CURRENT_READER(_val) \ +do \ +{ \ + SCM_FAST_FLUID_SET_X (the_reader_fluid_num, (_val)); \ +} \ +while (0) + + +SCM_DEFINE (scm_current_reader, "current-reader", 0, 0, 0, + (void), + "Return the current reader.") +#define FUNC_NAME s_scm_current_reader +{ + return CURRENT_READER (); +} +#undef FUNC_NAME + +SCM_DEFINE (scm_set_current_reader, "set-current-reader", 1, 0, 0, + (SCM reader), + "Set the current reader to @var{reader} and return the " + "previous current reader.") +#define FUNC_NAME s_scm_set_current_reader +{ + SCM previous; + + /* The value `#f' is a special allowed value for READER which means ``use + Guile's built-in reader''. See how `primitive-load' uses it as an + optimization. */ + if (reader != SCM_BOOL_F) + SCM_VALIDATE_PROC (1, reader); + + previous = CURRENT_READER (); + SET_CURRENT_READER (reader); + + return previous; +} +#undef FUNC_NAME + + +\f /* Loading a file, given an absolute filename. */ /* Hook to run when we load a file, perhaps to announce the fact somewhere. Applied to the full name of the file. */ static SCM *scm_loc_load_hook; -SCM_DEFINE (scm_primitive_load, "primitive-load", 1, 0, 0, +SCM_DEFINE (scm_primitive_load, "primitive-load", 1, 0, 0, (SCM filename), "Load the file named @var{filename} and evaluate its contents in\n" "the top-level environment. The load paths are not searched;\n" @@ -88,9 +135,19 @@ while (1) { - SCM form = scm_read (port); + SCM reader, form; + + /* Use whatever the current reader is. */ + reader = CURRENT_READER (); + + 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); } @@ -501,6 +558,10 @@ scm_nullstr))); scm_loc_load_hook = SCM_VARIABLE_LOC (scm_c_define ("%load-hook", SCM_BOOL_F)); + the_reader = scm_permanent_object (scm_make_fluid ()); + the_reader_fluid_num = SCM_FLUID_NUM (the_reader); + SET_CURRENT_READER (SCM_BOOL_F); + init_build_info (); #include "libguile/load.x" --- orig/libguile/load.h +++ mod/libguile/load.h @@ -38,6 +38,9 @@ SCM_API SCM scm_c_primitive_load_path (const char *filename); SCM_API void scm_init_load (void); +SCM_API SCM scm_current_reader (void); +SCM_API SCM scm_set_current_reader (SCM reader); + #endif /* SCM_LOAD_H */ /* --- orig/libguile/modules.h +++ mod/libguile/modules.h @@ -45,6 +45,7 @@ #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_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 ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-11-07 16:06 ` [PATCH] Per-module reader, take #3 Ludovic Courtès @ 2005-11-16 21:13 ` Neil Jerram 2005-11-17 10:03 ` Ludovic Courtès 2005-11-20 0:15 ` Marius Vollmer 0 siblings, 2 replies; 50+ messages in thread From: Neil Jerram @ 2005-11-16 21:13 UTC (permalink / raw) ludovic.courtes@laas.fr (Ludovic Courtès) writes: > Agreed, this approach is consistent with the current `load' stack. > > The patch below does what you described. I left the `#:reader' option > to `define-module' as an alternative, higher-level approach to choosing > an alternate reader. > > Please let me know what you think about it. And sorry for consuming so > much of your time! ;-) I still don't like the module option (no surprise there), and I think that the other parts of the patch could be made a bit simpler (which to my mind is a Good Thing). To be completely concrete about what I mean, here is a version of your patch which I prefer (untested except by make check). Please let me know what you think. Neil Index: doc/ref/api-evaluation.texi =================================================================== RCS file: /cvsroot/guile/guile/guile-core/doc/ref/api-evaluation.texi,v retrieving revision 1.5 diff -u -u -r1.5 api-evaluation.texi --- doc/ref/api-evaluation.texi 2 Mar 2005 20:46:41 -0000 1.5 +++ doc/ref/api-evaluation.texi 16 Nov 2005 21:12:28 -0000 @@ -409,12 +409,24 @@ @subsection Loading Scheme Code from File @rnindex load -@deffn {Scheme Procedure} load filename +@deffn {Scheme Procedure} load filename [reader] Load @var{filename} and evaluate its contents in the top-level -environment. The load paths are not searched. If the variable -@code{%load-hook} is defined, it should be bound to a procedure that -will be called before any code is loaded. See documentation for -@code{%load-hook} later in this section. +environment. The load paths are not searched. + +@var{reader} if provided should be either @code{#f}, or a procedure with +the signature @code{(lambda (port) @dots{})} which reads the next +expression from @var{port}. If @var{reader} is @code{#f} or absent, +Guile's built-in @code{read} procedure is used (@pxref{Scheme Read}). + +The @var{reader} argument takes effect by setting the value of the +@code{current-reader} fluid (see below) before loading the file, and +restoring its previous value when loading is complete. The Scheme code +inside @var{filename} can itself change the current reader procedure on +the fly by setting @code{current-reader} fluid. + +If the variable @code{%load-hook} is defined, it should be bound to a +procedure that will be called before any code is loaded. See +documentation for @code{%load-hook} later in this section. @end deffn @deffn {Scheme Procedure} load-from-path filename @@ -451,6 +463,15 @@ in the @code{%load-extensions} list; @code{%search-load-path} will try each extension automatically. @end deffn + +@defvar current-reader +@code{current-reader} holds the read procedure that is currently being +used by the above loading procedures to read expressions (from the file +that they are loading). @code{current-reader} is a fluid, so it has an +independent value in each dynamic root and should be read and set using +@code{fluid-ref} and @code{fluid-set!} (@pxref{Fluids and Dynamic +States}). +@end defvar @defvar %load-hook A procedure to be called @code{(%load-hook @var{filename})} whenever a 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 -u -r1.351 boot-9.scm --- ice-9/boot-9.scm 31 Jul 2005 23:36:50 -0000 1.351 +++ ice-9/boot-9.scm 16 Nov 2005 21:12:29 -0000 @@ -1635,17 +1635,19 @@ (define basic-load load) -(define (load-module filename) +(define (load-module filename . reader) (save-module-excursion (lambda () (let ((oldname (and (current-load-port) (port-filename (current-load-port))))) - (basic-load (if (and oldname - (> (string-length filename) 0) - (not (char=? (string-ref filename 0) #\/)) - (not (string=? (dirname oldname) "."))) - (string-append (dirname oldname) "/" filename) - filename)))))) + (apply basic-load + (if (and oldname + (> (string-length filename) 0) + (not (char=? (string-ref filename 0) #\/)) + (not (string=? (dirname oldname) "."))) + (string-append (dirname oldname) "/" filename) + filename) + reader))))) \f Index: ice-9/r4rs.scm =================================================================== RCS file: /cvsroot/guile/guile/guile-core/ice-9/r4rs.scm,v retrieving revision 1.17 diff -u -u -r1.17 r4rs.scm --- ice-9/r4rs.scm 23 May 2005 19:57:19 -0000 1.17 +++ ice-9/r4rs.scm 16 Nov 2005 21:12:29 -0000 @@ -206,6 +206,8 @@ (set! %load-hook %load-announce) -(define (load name) - (start-stack 'load-stack - (primitive-load name))) +(define (load name . reader) + (with-fluid* current-reader (and (pair? reader) (car reader)) + (lambda () + (start-stack 'load-stack + (primitive-load name))))) Index: libguile/load.c =================================================================== RCS file: /cvsroot/guile/guile/guile-core/libguile/load.c,v retrieving revision 1.86 diff -u -u -r1.86 load.c --- libguile/load.c 23 May 2005 19:57:20 -0000 1.86 +++ libguile/load.c 16 Nov 2005 21:12:29 -0000 @@ -42,6 +42,7 @@ #include "libguile/validate.h" #include "libguile/load.h" +#include "libguile/fluids.h" #include <sys/types.h> #include <sys/stat.h> @@ -61,6 +62,10 @@ Applied to the full name of the file. */ static SCM *scm_loc_load_hook; +/* The current reader (a fluid). */ +static SCM the_reader = SCM_BOOL_F; +static size_t the_reader_fluid_num = 0; + SCM_DEFINE (scm_primitive_load, "primitive-load", 1, 0, 0, (SCM filename), "Load the file named @var{filename} and evaluate its contents in\n" @@ -88,9 +93,19 @@ while (1) { - SCM form = scm_read (port); + SCM reader, form; + + /* Lookup and use the current reader to read the next + expression. */ + reader = SCM_FAST_FLUID_REF (the_reader_fluid_num); + 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); } @@ -500,6 +515,11 @@ scm_list_2 (scm_from_locale_string (".scm"), scm_nullstr))); scm_loc_load_hook = SCM_VARIABLE_LOC (scm_c_define ("%load-hook", SCM_BOOL_F)); + + the_reader = scm_make_fluid (); + the_reader_fluid_num = SCM_FLUID_NUM (the_reader); + SCM_FAST_FLUID_SET_X (the_reader_fluid_num, SCM_BOOL_F); + scm_c_define("current-reader", the_reader); init_build_info (); _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-11-16 21:13 ` Neil Jerram @ 2005-11-17 10:03 ` Ludovic Courtès 2005-11-20 0:15 ` Marius Vollmer 1 sibling, 0 replies; 50+ messages in thread From: Ludovic Courtès @ 2005-11-17 10:03 UTC (permalink / raw) Cc: guile-devel Neil Jerram <neil@ossau.uklinux.net> writes: > I still don't like the module option (no surprise there), and I think > that the other parts of the patch could be made a bit simpler (which > to my mind is a Good Thing). To be completely concrete about what I > mean, here is a version of your patch which I prefer (untested except > by make check). Please let me know what you think. It seems equally acceptable to me. Originally, I decided to not expose the `current-reader' fluid in order to be consistent with other "stealthy" uses of fluids, like `current-module' (the fluid itself is not exported, only a setter and a getter are). But this has the drawback of requiring the `dynamic-wind' hair in `basic-load'. And it also looks more mysterious or magic to user, which is not a good thing. So either way will be fine to me. Thanks! Ludovic. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-11-16 21:13 ` Neil Jerram 2005-11-17 10:03 ` Ludovic Courtès @ 2005-11-20 0:15 ` Marius Vollmer 2005-11-21 12:55 ` Ludovic Courtès 2005-12-03 20:02 ` Neil Jerram 1 sibling, 2 replies; 50+ messages in thread From: Marius Vollmer @ 2005-11-20 0:15 UTC (permalink / raw) Cc: guile-devel Neil Jerram <neil@ossau.uklinux.net> writes: > To be completely concrete about what I mean, here is a version of > your patch which I prefer (untested except by make check). Hmm. Your approach make 'load' configurable so that it can use different 'read' procedures. Wouldn't it be more natural to make 'read' configurable to parse different syntaxes? 'load' is only a thin wrapper around 'read' and 'eval' (basically, a repl without the 'p'). The real meat is in 'read' (syntax) and 'eval' (semantics). So, if we want to customize the syntax, I'd say 'read' is the place to do it. Then all users of 'read' would automatically use the new syntax, not only when reading code in 'load'. (That's one big point of Lisp, that the data and code syntax are the same.) However, making the read procedure used by 'load' configurable can't hurt, I think. -- GPG: D5D4E405 - 2F9B BCCC 8527 692A 04E3 331E FAF8 226A D5D4 E405 _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-11-20 0:15 ` Marius Vollmer @ 2005-11-21 12:55 ` Ludovic Courtès 2005-12-03 20:02 ` Neil Jerram 1 sibling, 0 replies; 50+ messages in thread From: Ludovic Courtès @ 2005-11-21 12:55 UTC (permalink / raw) Cc: guile-devel, Neil Jerram Hi Marius, Marius Vollmer <mvo@zagadka.de> writes: > Hmm. Your approach make 'load' configurable so that it can use > different 'read' procedures. Wouldn't it be more natural to make > 'read' configurable to parse different syntaxes? [...] > However, making the read procedure used by 'load' configurable can't > hurt, I think. Indeed. In fact, this change is two-fold: 1. Have `primitive-load' refer to the `*current-reader*'[*] fluid instead of hard-wiring calls to `scm_read ()'. This way, a Scheme file being loaded can change its reader on-the-fly by doing: (fluid-set! *current-reader* ...) This allows a module to use a different syntax variant, for instance. 2. There are several functions that build upon `primitive-load'. Neil identified them and proposed a way to cleanly integrate them with our modified `primitive-load' while still keeping the "primitiveness" or `primitive-load': http://lists.gnu.org/archive/html/guile-devel/2005-10/msg00116.html Since those `load' procedures are written in Scheme, we can harmlessly have them take an optional `read' argument. Hope this helps, Ludovic. [*] It occurred to me that Neil named the fluid `current-reader' but I think it should really be `*current-reader*' in order to stick to the conventions. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-11-20 0:15 ` Marius Vollmer 2005-11-21 12:55 ` Ludovic Courtès @ 2005-12-03 20:02 ` Neil Jerram 2005-12-05 8:31 ` Ludovic Courtès 2005-12-07 0:04 ` Marius Vollmer 1 sibling, 2 replies; 50+ messages in thread From: Neil Jerram @ 2005-12-03 20:02 UTC (permalink / raw) Cc: guile-devel Marius Vollmer <mvo@zagadka.de> writes: > Neil Jerram <neil@ossau.uklinux.net> writes: > >> To be completely concrete about what I mean, here is a version of >> your patch which I prefer (untested except by make check). > > Hmm. Your approach make 'load' configurable so that it can use > different 'read' procedures. Wouldn't it be more natural to make > 'read' configurable to parse different syntaxes? > > 'load' is only a thin wrapper around 'read' and 'eval' (basically, a > repl without the 'p'). The real meat is in 'read' (syntax) and 'eval' > (semantics). So, if we want to customize the syntax, I'd say 'read' > is the place to do it. Then all users of 'read' would automatically > use the new syntax, not only when reading code in 'load'. (That's one > big point of Lisp, that the data and code syntax are the same.) That was my one of my first thoughts also (see towards the end of http://lists.gnu.org/archive/html/guile-devel/2005-09/msg00035.html). But now I'm not sure that it makes sense. If you are reading expressions by hand, and you want to use an alternative reader to do so, you can just call (alternative-read port) - there's no need to make the normal `read' configurable. On the other hand, the reason for allowing `load' to be configurable (with an alternative reader) is pretty much exactly the same as the reason why we think it's useful to provide `load' at all: that is, just that it's too boring to ask developers to write the same read eval loop over and over again, even though they could. Finally, although we might in theory be able to accommodate all possible reading variants as configurable options to the default read, in practice (i) this would be a pain for anyone wanting a variant that hasn't yet been incorporated into Guile's official reader, because they'd have to argue for it and then wait until it filtered through to a release, and (ii) we'd still need to implement something to make it easy to confine the effect/scope of read options to particular files, because the common case is that particular files require particular read variants. Taking (i) and (ii), it seems a lot simpler just to allow the Guile developer to specify an alternative read procedure for a particular load operation. > However, making the read procedure used by 'load' configurable can't > hurt, I think. OK, thanks. I'll just wait a few days in case you or anyone else have further comments. If not I'll commit the patch as proposed. Regards, Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-12-03 20:02 ` Neil Jerram @ 2005-12-05 8:31 ` Ludovic Courtès 2005-12-07 0:04 ` Marius Vollmer 1 sibling, 0 replies; 50+ messages in thread From: Ludovic Courtès @ 2005-12-05 8:31 UTC (permalink / raw) Cc: guile-devel Hi, Neil Jerram <neil@ossau.uklinux.net> writes: > Finally, although we might in theory be able to accommodate all > possible reading variants as configurable options to the default read, > in practice (i) this would be a pain for anyone wanting a variant that > hasn't yet been incorporated into Guile's official reader, because > they'd have to argue for it and then wait until it filtered through to > a release, and (ii) we'd still need to implement something to make it > easy to confine the effect/scope of read options to particular files, > because the common case is that particular files require particular > read variants. Taking (i) and (ii), it seems a lot simpler just to > allow the Guile developer to specify an alternative read procedure for > a particular load operation. [Advertisement] And `guile-reader' would happily come into the picture to help solve (i), because it allows reader variants to be easily implemented (be it in C or Scheme) and combined with the rest of a reader. http://savannah.nongnu.org/projects/guile-reader/ No more "pain", no need to endlessly argue and "wait until it filtered through a release"! :-) Thanks, Ludovic. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-12-03 20:02 ` Neil Jerram 2005-12-05 8:31 ` Ludovic Courtès @ 2005-12-07 0:04 ` Marius Vollmer 2005-12-14 1:00 ` Neil Jerram 1 sibling, 1 reply; 50+ messages in thread From: Marius Vollmer @ 2005-12-07 0:04 UTC (permalink / raw) Cc: guile-devel Neil Jerram <neil@ossau.uklinux.net> writes: >> However, making the read procedure used by 'load' configurable can't >> hurt, I think. > > OK, thanks. I'll just wait a few days in case you or anyone else have > further comments. If not I'll commit the patch as proposed. Yes, please do. I still don't see the big point behind it, and I was about to say "compiler" ;-), but let's see how people are going to use this. Please make sure we have adequate docs, of course. As a related comment, I think we should make our own reader highly configurable at one point, along the lines of Common Lisp read-tables maybe, or by following established Scheme standards. -- GPG: D5D4E405 - 2F9B BCCC 8527 692A 04E3 331E FAF8 226A D5D4 E405 _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-12-07 0:04 ` Marius Vollmer @ 2005-12-14 1:00 ` Neil Jerram 2005-12-14 14:06 ` Ludovic Courtès 2006-01-11 16:45 ` Ludovic Courtès 0 siblings, 2 replies; 50+ messages in thread From: Neil Jerram @ 2005-12-14 1:00 UTC (permalink / raw) Cc: guile-devel Marius Vollmer <mvo@zagadka.de> writes: > Neil Jerram <neil@ossau.uklinux.net> writes: > >>> However, making the read procedure used by 'load' configurable can't >>> hurt, I think. >> >> OK, thanks. I'll just wait a few days in case you or anyone else have >> further comments. If not I'll commit the patch as proposed. > > Yes, please do. I still don't see the big point behind it, and I was > about to say "compiler" ;-), but let's see how people are going to use > this. Please make sure we have adequate docs, of course. This is in CVS now. > As a related comment, I think we should make our own reader highly > configurable at one point, along the lines of Common Lisp read-tables > maybe, or by following established Scheme standards. Yes, sounds good. The configurable 'load' reader may help us towards that goal, by allowing people to experiment easily with what kinds of reader configurability are useful, and what kind of API is convenient to control it. Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-12-14 1:00 ` Neil Jerram @ 2005-12-14 14:06 ` Ludovic Courtès 2005-12-14 19:37 ` Neil Jerram 2006-01-11 16:45 ` Ludovic Courtès 1 sibling, 1 reply; 50+ messages in thread From: Ludovic Courtès @ 2005-12-14 14:06 UTC (permalink / raw) Cc: guile-devel Hi, Neil Jerram <neil@ossau.uklinux.net> writes: > This is in CVS now. Thanks Neil! BTW, what do you think of `*current-reader*' instead of `current-reader' as a fluid name? It would be more conventional and consistent with the rest of Guile (e.g., `current-module' names a procedure, not the fluid itself). > Yes, sounds good. The configurable 'load' reader may help us towards > that goal, by allowing people to experiment easily with what kinds of > reader configurability are useful, and what kind of API is convenient > to control it. Precisely, `guile-reader' is meant to be an equivalent of CL's read table. Thanks, Ludovic. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-12-14 14:06 ` Ludovic Courtès @ 2005-12-14 19:37 ` Neil Jerram 2005-12-15 9:13 ` Ludovic Courtès 0 siblings, 1 reply; 50+ messages in thread From: Neil Jerram @ 2005-12-14 19:37 UTC (permalink / raw) Cc: guile-devel ludovic.courtes@laas.fr (Ludovic Courtès) writes: > Hi, > > Neil Jerram <neil@ossau.uklinux.net> writes: > >> This is in CVS now. > > Thanks Neil! BTW, what do you think of `*current-reader*' instead of > `current-reader' as a fluid name? What other *star* names do we have? I can only think of *features*. Personally I don't like this semi-convention much. Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-12-14 19:37 ` Neil Jerram @ 2005-12-15 9:13 ` Ludovic Courtès 2005-12-15 19:47 ` Neil Jerram 0 siblings, 1 reply; 50+ messages in thread From: Ludovic Courtès @ 2005-12-15 9:13 UTC (permalink / raw) Cc: guile-devel Hi, Neil Jerram <neil@ossau.uklinux.net> writes: > What other *star* names do we have? I can only think of *features*. We don't have any other star name, but so far we did not export any fluid, only getters and setters (e.g., `current-module'). The most important thing is to be consistent with the naming scheme of those getters and setters, no matter what naming convention we follow for fluids. It turns out that star names are a convention for dynamically-scoped variables in Common Lisp. OTOH, http://community.schemewiki.org/?variable-naming-convention suggests a different naming convention. Thanks, Ludovic. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-12-15 9:13 ` Ludovic Courtès @ 2005-12-15 19:47 ` Neil Jerram 2005-12-16 6:13 ` Tomas Zerolo 2005-12-16 8:55 ` Ludovic Courtès 0 siblings, 2 replies; 50+ messages in thread From: Neil Jerram @ 2005-12-15 19:47 UTC (permalink / raw) ludovic.courtes@laas.fr (Ludovic Courtès) writes: > OTOH, http://community.schemewiki.org/?variable-naming-convention > suggests a different naming convention. Now that really is a horrible convention. Hmm, how can we best confuse someone coming to Scheme from another language for the first time? For `current-reader' I think we should stick as we are. Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-12-15 19:47 ` Neil Jerram @ 2005-12-16 6:13 ` Tomas Zerolo 2005-12-16 8:32 ` Neil Jerram 2005-12-16 8:55 ` Ludovic Courtès 1 sibling, 1 reply; 50+ messages in thread From: Tomas Zerolo @ 2005-12-16 6:13 UTC (permalink / raw) Cc: guile-devel [-- Attachment #1.1: Type: text/plain, Size: 626 bytes --] On Thu, Dec 15, 2005 at 07:47:13PM +0000, Neil Jerram wrote: > ludovic.courtes@laas.fr (Ludovic Courtès) writes: > > > OTOH, http://community.schemewiki.org/?variable-naming-convention > > suggests a different naming convention. > > Now that really is a horrible convention. Hmm, how can we best > confuse someone coming to Scheme from another language for the first > time? To be fair, they seem just to be reporting on current use (which is an useful service). Now I'm not implying to say that I like current use (which is somewhat fragmented across Scheme implementations as well). Regards -- tomas [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] [-- Attachment #2: Type: text/plain, Size: 143 bytes --] _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-12-16 6:13 ` Tomas Zerolo @ 2005-12-16 8:32 ` Neil Jerram 2005-12-16 9:21 ` Tomas Zerolo 0 siblings, 1 reply; 50+ messages in thread From: Neil Jerram @ 2005-12-16 8:32 UTC (permalink / raw) Cc: guile-devel tomas@tuxteam.de (Tomas Zerolo) writes: > On Thu, Dec 15, 2005 at 07:47:13PM +0000, Neil Jerram wrote: >> ludovic.courtes@laas.fr (Ludovic Courtès) writes: >> >> > OTOH, http://community.schemewiki.org/?variable-naming-convention >> > suggests a different naming convention. >> >> Now that really is a horrible convention. Hmm, how can we best >> confuse someone coming to Scheme from another language for the first >> time? > > To be fair, they seem just to be reporting on current use (which is an > useful service). I wasn't criticising the people who compiled the Wiki page; it's a very useful page. I'm specifically casting aspersions on the idea of the apparent `$name' convention for fluids. Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-12-16 8:32 ` Neil Jerram @ 2005-12-16 9:21 ` Tomas Zerolo 0 siblings, 0 replies; 50+ messages in thread From: Tomas Zerolo @ 2005-12-16 9:21 UTC (permalink / raw) Cc: Tomas Zerolo, guile-devel [-- Attachment #1.1: Type: text/plain, Size: 928 bytes --] On Fri, Dec 16, 2005 at 08:32:02AM +0000, Neil Jerram wrote: > tomas@tuxteam.de (Tomas Zerolo) writes: > > > On Thu, Dec 15, 2005 at 07:47:13PM +0000, Neil Jerram wrote: > >> ludovic.courtes@laas.fr (Ludovic Courtès) writes: > >> > >> > OTOH, http://community.schemewiki.org/?variable-naming-convention > >> > suggests a different naming convention. > >> > >> Now that really is a horrible convention. Hmm, how can we best > >> confuse someone coming to Scheme from another language for the first > >> time? > > > > To be fair, they seem just to be reporting on current use (which is an > > useful service). > > I wasn't criticising the people who compiled the Wiki page; it's a > very useful page. I'm specifically casting aspersions on the idea of > the apparent `$name' convention for fluids. Right, sorry. On re-reading this is definitely the more plausible interpretation. regards -- tomas [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] [-- Attachment #2: Type: text/plain, Size: 143 bytes --] _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-12-15 19:47 ` Neil Jerram 2005-12-16 6:13 ` Tomas Zerolo @ 2005-12-16 8:55 ` Ludovic Courtès 2005-12-17 10:26 ` Neil Jerram 1 sibling, 1 reply; 50+ messages in thread From: Ludovic Courtès @ 2005-12-16 8:55 UTC (permalink / raw) Cc: guile-devel Neil Jerram <neil@ossau.uklinux.net> writes: > For `current-reader' I think we should stick as we are. Then, should we go ahead and remove the `current-module' and `set-current-module' procedures in favor of `current-module' as a fluid? By not exporting the fluid directly, my original patch kept away from such a highly controversial debate. ;-) The "principle of least surprise" _is_ important for people coming to the language/implementation. Thanks, Ludovic. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-12-16 8:55 ` Ludovic Courtès @ 2005-12-17 10:26 ` Neil Jerram 2005-12-17 13:09 ` Marius Vollmer 0 siblings, 1 reply; 50+ messages in thread From: Neil Jerram @ 2005-12-17 10:26 UTC (permalink / raw) ludovic.courtes@laas.fr (Ludovic Courtès) writes: > Neil Jerram <neil@ossau.uklinux.net> writes: > >> For `current-reader' I think we should stick as we are. > > Then, should we go ahead and remove the `current-module' and > `set-current-module' procedures in favor of `current-module' as a fluid? > By not exporting the fluid directly, my original patch kept away from > such a highly controversial debate. ;-) :-) If we were starting from a clean slate, then yes, I'd agree. But starting from where we are now, I don't think it's worth changing what already exists. Note BTW that both current-module and current-reader are Guile-specific. For implementing something not Guile-specific, we should also take into account portability of the chosen syntax; but for these cases we don't need to. (Sudden confusion: Are fluids part of R5RS? If so, why do we need the parameters SRFI? I guess I need to go and reread it.) > The "principle of least surprise" _is_ important for people coming to > the language/implementation. Yes, but as ever there are other principles too, in this case back compatibility and simplicity. Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-12-17 10:26 ` Neil Jerram @ 2005-12-17 13:09 ` Marius Vollmer 2005-12-29 10:27 ` Neil Jerram 0 siblings, 1 reply; 50+ messages in thread From: Marius Vollmer @ 2005-12-17 13:09 UTC (permalink / raw) Cc: guile-devel Neil Jerram <neil@ossau.uklinux.net> writes: > (Sudden confusion: Are fluids part of R5RS? If so, why do we need the > parameters SRFI? I guess I need to go and reread it.) No no no, fluids are not part of R5RS. I think we should implement the parameter SRFI in the core and start using it for things like current-module, current-error-port etc. Fluids can now be garbage collected and might thus be a viable implementation for the parameter SRFI. I would have to check. -- GPG: D5D4E405 - 2F9B BCCC 8527 692A 04E3 331E FAF8 226A D5D4 E405 _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-12-17 13:09 ` Marius Vollmer @ 2005-12-29 10:27 ` Neil Jerram 0 siblings, 0 replies; 50+ messages in thread From: Neil Jerram @ 2005-12-29 10:27 UTC (permalink / raw) Cc: guile-devel Marius Vollmer <mvo@zagadka.de> writes: > Neil Jerram <neil@ossau.uklinux.net> writes: > >> (Sudden confusion: Are fluids part of R5RS? If so, why do we need the >> parameters SRFI? I guess I need to go and reread it.) > > No no no, fluids are not part of R5RS. I think we should implement > the parameter SRFI in the core and start using it for things like > current-module, current-error-port etc. OK, that makes sense; thanks for explaining. Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2005-12-14 1:00 ` Neil Jerram 2005-12-14 14:06 ` Ludovic Courtès @ 2006-01-11 16:45 ` Ludovic Courtès 2006-01-13 17:38 ` Neil Jerram 1 sibling, 1 reply; 50+ messages in thread From: Ludovic Courtès @ 2006-01-11 16:45 UTC (permalink / raw) Cc: guile-devel [`current-reader' stuff...] Neil Jerram <neil@ossau.uklinux.net> writes: > This is in CVS now. I think there's another bit that should get in too: --- ../../guile-core--cvs/ice-9/boot-9.scm 2005-12-14 14:58:29.000000000 +0100 +++ boot-9.scm 2006-01-05 11:19:34.901389352 +0100 @@ -2540,7 +2540,7 @@ (display prompt) (force-output) (run-hook before-read-hook) - (read (current-input-port)))) + ((or (fluid-ref current-reader) read) (current-input-port)))) (define (scm-style-repl) Thanks, Ludovic. _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader, take #3 2006-01-11 16:45 ` Ludovic Courtès @ 2006-01-13 17:38 ` Neil Jerram 0 siblings, 0 replies; 50+ messages in thread From: Neil Jerram @ 2006-01-13 17:38 UTC (permalink / raw) Cc: guile-devel ludovic.courtes@laas.fr (Ludovic Courtès) writes: > [`current-reader' stuff...] > > Neil Jerram <neil@ossau.uklinux.net> writes: > >> This is in CVS now. > > I think there's another bit that should get in too: Thanks, applied. In my view this is a bit separate from the use of current-reader in loading files, but it seems useful and I don't think it has any problematic overlap with the loading use. If we had some documentation about the REPL, it should be enhanced to mention this; but I don't think we have REPL documentation at all yet. Would anyone like to check and (if necessary) write some? (It could also mention using the debugger when an error occurs, use of history variables; anything else?) Regards, Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH] Per-module reader 2005-09-27 8:21 ` Ludovic Courtès 2005-10-11 11:26 ` Ludovic Courtès @ 2005-10-19 22:56 ` Neil Jerram 1 sibling, 0 replies; 50+ messages in thread From: Neil Jerram @ 2005-10-19 22:56 UTC (permalink / raw) Ludovic, Just one remaining loose end from your previous email ... > As for circular dependencies, I think there's nothing special here: the > problem is the same as for any other binding. Strictly no, there's nothing special, but in practice there is. This is because modules normally consist mostly of defines which delay the evaluation of their procedure bodies ... which generally allows circular dependencies not to be a problem. In the reader case, however, the reader is used during the initial evaluation of the module code. So for example: (define-module (A) | (define-module (B) #:use-module (B) | #:use-module (A) #:export (a-proc)) | #:export (b-proc)) | (define (a-proc) b-proc) | (define (b-proc) a-proc) is fine, but (define-module (A) | (define-module (B) #:use-module (B) | #:use-module (A) #:reader b-reader | #:export (b-reader)) #:export (a-proc)) | | (define (a-proc) ...) | (define (b-reader) ...) is only OK if the loading of (A) is initiated before that of (B). Regards, Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel ^ permalink raw reply [flat|nested] 50+ messages in thread
end of thread, other threads:[~2006-01-13 17:38 UTC | newest] Thread overview: 50+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2005-09-13 12:51 [PATCH] Per-module reader Ludovic Courtès 2005-09-26 12:29 ` Ludovic Courtès 2005-09-26 22:55 ` Kevin Ryde 2005-09-27 9:04 ` Ludovic Courtès 2005-09-26 19:05 ` Neil Jerram 2005-09-27 8:21 ` Ludovic Courtès 2005-10-11 11:26 ` Ludovic Courtès 2005-10-11 23:24 ` Neil Jerram 2005-10-12 9:11 ` Ludovic Courtès 2005-10-17 9:17 ` [PATCH] Per-module reader, take #2 Ludovic Courtès 2005-10-17 20:41 ` Neil Jerram 2005-10-18 7:42 ` Ludovic Courtès 2005-10-19 22:23 ` Neil Jerram 2005-10-20 1:22 ` Kevin Ryde 2005-10-20 7:59 ` Ludovic Courtès 2005-10-20 19:30 ` Kevin Ryde 2005-10-20 21:27 ` Neil Jerram 2005-10-20 7:48 ` Ludovic Courtès 2005-10-20 10:52 ` Tomas Zerolo 2005-10-20 14:42 ` Ludovic Courtès 2005-10-20 22:09 ` Neil Jerram 2005-10-21 7:43 ` Ludovic Courtès 2005-10-24 11:43 ` Ludovic Courtès 2005-10-28 21:26 ` Neil Jerram 2005-10-28 22:38 ` Kevin Ryde 2005-10-29 8:58 ` Neil Jerram 2005-10-30 19:55 ` Neil Jerram 2005-11-07 16:06 ` [PATCH] Per-module reader, take #3 Ludovic Courtès 2005-11-16 21:13 ` Neil Jerram 2005-11-17 10:03 ` Ludovic Courtès 2005-11-20 0:15 ` Marius Vollmer 2005-11-21 12:55 ` Ludovic Courtès 2005-12-03 20:02 ` Neil Jerram 2005-12-05 8:31 ` Ludovic Courtès 2005-12-07 0:04 ` Marius Vollmer 2005-12-14 1:00 ` Neil Jerram 2005-12-14 14:06 ` Ludovic Courtès 2005-12-14 19:37 ` Neil Jerram 2005-12-15 9:13 ` Ludovic Courtès 2005-12-15 19:47 ` Neil Jerram 2005-12-16 6:13 ` Tomas Zerolo 2005-12-16 8:32 ` Neil Jerram 2005-12-16 9:21 ` Tomas Zerolo 2005-12-16 8:55 ` Ludovic Courtès 2005-12-17 10:26 ` Neil Jerram 2005-12-17 13:09 ` Marius Vollmer 2005-12-29 10:27 ` Neil Jerram 2006-01-11 16:45 ` Ludovic Courtès 2006-01-13 17:38 ` Neil Jerram 2005-10-19 22:56 ` [PATCH] Per-module reader Neil Jerram
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).