* [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-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 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 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-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-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
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
* 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-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 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: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: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-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-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: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-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
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).