From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: ludovic.courtes@laas.fr (Ludovic =?iso-8859-1?Q?Court=E8s?=) Newsgroups: gmane.lisp.guile.devel Subject: Re: [PATCH] Per-module reader, take #2 Date: Mon, 17 Oct 2005 11:17:37 +0200 Organization: LAAS-CNRS Message-ID: <8764rw7b9q.fsf_-_@laas.fr> References: <87u0gp9lm3.fsf@laas.fr> <877jd3lkdq.fsf@ossau.uklinux.net> <87hdc62a6c.fsf@laas.fr> <87irw49twc.fsf@laas.fr> <87irw3prgp.fsf@ossau.uklinux.net> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: sea.gmane.org 1129543859 15530 80.91.229.2 (17 Oct 2005 10:10:59 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Mon, 17 Oct 2005 10:10:59 +0000 (UTC) Cc: guile-devel@gnu.org Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Mon Oct 17 12:10:57 2005 Return-path: Original-Received: from lists.gnu.org ([199.232.76.165]) by ciao.gmane.org with esmtp (Exim 4.43) id 1ERRwe-0003XN-1S for guile-devel@m.gmane.org; Mon, 17 Oct 2005 12:10:16 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1ERRwc-00025c-Q4 for guile-devel@m.gmane.org; Mon, 17 Oct 2005 06:10:14 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1ERRIC-0004qX-0b for guile-devel@gnu.org; Mon, 17 Oct 2005 05:28:28 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1ERRHT-0004FW-5h for guile-devel@gnu.org; Mon, 17 Oct 2005 05:27:44 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1ERRAu-0003fR-1e for guile-devel@gnu.org; Mon, 17 Oct 2005 05:20:58 -0400 Original-Received: from [140.93.0.15] (helo=laas.laas.fr) by monty-python.gnu.org with esmtp (TLS-1.0:DHE_RSA_3DES_EDE_CBC_SHA:24) (Exim 4.34) id 1ERRAt-0007FD-S0 for guile-devel@gnu.org; Mon, 17 Oct 2005 05:20:56 -0400 Original-Received: by laas.laas.fr (8.13.1/8.13.4) with SMTP id j9H9KpB3029202; Mon, 17 Oct 2005 11:20:54 +0200 (CEST) Original-To: Neil Jerram X-URL: http://www.laas.fr/~lcourtes/ X-Revolutionary-Date: 26 =?iso-8859-1?Q?Vend=E9miaire?= an 214 de la =?iso-8859-1?Q?R=E9volution?= X-PGP-Key-ID: 0xEB1F5364 X-PGP-Key: http://www.laas.fr/~lcourtes/ludovic.asc X-PGP-Fingerprint: 821D 815D 902A 7EAB 5CEE D120 7FBA 3D4F EB1F 5364 X-OS: powerpc-unknown-linux-gnu Mail-Followup-To: Neil Jerram , guile-devel@gnu.org In-Reply-To: <87irw3prgp.fsf@ossau.uklinux.net> (Neil Jerram's message of "Wed, 12 Oct 2005 00:24:38 +0100") User-Agent: Gnus/5.110004 (No Gnus v0.4) Emacs/21.4 (gnu/linux) X-Spam-Score: 0 () X-Scanned-By: MIMEDefang at CNRS-LAAS X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Errors-To: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.devel:5301 Archived-At: Hi, Neil Jerram 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 #include @@ -55,13 +56,59 @@ #endif +/* 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 + + + /* 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