Re: r6rs libraries, round three

2009-12-28 Thread Ludovic Courtès
Hello,

Neil Jerram n...@ossau.uklinux.net writes:

 Julian Graham jool...@gmail.com writes:

 On a related note, I assume Emacs' `scheme-mode' has been adding
 unwanted tabs?  What should I do to correct this in my local
 environment?

 (setq indent-tabs-mode nil)

We should put that in ‘.dir-locals.el’, once for all.

Thanks,
Ludo’.





Re: r6rs libraries, round three

2009-12-27 Thread Julian Graham
Hi all,

Find attached a revised and polished version of the `(ice-9
r6rs-libraries)' module I submitted a couple of months ago.  This
version includes the following changes:

* The library transformer code's been cleaned up and compacted (by
more than 30%) and now uses a `defmacro' form similar to the one used
by `use-modules' and `define-module' instead of the messy
syncase-based transformer it was using originally.

* I've re-organized the code to more closely resemble the structure of
`use-modules' and 'define-module' -- the macros delegate syntax
parsing to a set of processing functions.  In addition to making the
macros simpler, this should make it easier to unify the module and
library systems in the future, if desired.

* I've added an `import' macro as specified by R6RS 8.1 Top Level
Program Syntax [0].

* The module also supports the convention, specified by SRFI-97, that
SRFIs can be loaded as R6RS libraries by importing them as `(srfi
:[n])' -- my implementation transforms library names of that form to
the form used by Guile, `(srfi srfi-[n])'.

In case anyone missed the earlier emails on this topic, this module
contains macros that transform the R6RS `library' and 'import' forms
into Guile's native `define-module' and 'use-modules' forms.  In
concert with the version and binding export patches that were pushed
last week, this means that Guile now supports R6RS 7 Libraries [1],
and can thus share code (unmodified!) with any other conforming Scheme
implementation.

I consider this version of the code to be tentatively complete.  You
can try it out by dropping r6rs-libraries.scm into module/ice-9 and
then loading it in the REPL or including it as a dependency of a
normal Guile module.  I'm very interested in any feedback people might
have, particularly when it comes to the name of the module and where
it belongs / when it should be loaded (always?  Not in the REPL?).  If
no one objects, I'll add some documentation and push it.

As I mentioned to Andy on IRC, I'm working on a first pass at a set of
implementations of the R6RS Standard Libraries (minus the work already
done by Ludovic et al on bytevectors, etc.), as much as possible as
wrappers around Guile's existing functionality.  I should have some
status on that soon.


Regards,
Julian

[0] - http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-11.html#node_sec_8.1
[1] - http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-10.html#node_chap_7
;;; r6rs-libraries.scm --- Support for R6RS `library' and `import' forms

;;  Copyright (C) 2009 Free Software Foundation, Inc.
;;
;; This library is free software; you can redistribute it and/or
;; modify it under the terms of the GNU Lesser General Public
;; License as published by the Free Software Foundation; either
;; version 3 of the License, or (at your option) any later version.
;; 
;; This library is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;; Lesser General Public License for more details.
;; 
;; You should have received a copy of the GNU Lesser General Public
;; License along with this library; if not, write to the Free Software
;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
^L

(define-module (ice-9 r6rs-libraries)
  #:use-module (ice-9 optargs)
  #:use-module (ice-9 regex)
  #:use-module (srfi srfi-1)
  #:use-module (srfi srfi-2)
  #:use-module (srfi srfi-11)
  #:export-syntax (library import))

(define (name-and-version lst)
  (let-values (((head tail) (split-at lst (- (length lst) 1
(if (pair? (car tail)) (values head (car tail)) (values lst '()
(define srfi-regex (make-regexp ^\\:([0-9]+)$))

(define* (process-import args #:optional import-map)
  (define (flatten im)
(define (load-library library-ref)
  (define (transform-library-name name)
	(define (make-srfi m)
	  (cons 'srfi (list (string-symbol 
			 (string-append srfi- (match:substring m 1))
	(or (and (= (length name) 2)
		 (eq? (car name) 'srfi)
		 (and= (regexp-exec srfi-regex (symbol-string (cadr name)))
			make-srfi))
	name))
  (let-values (((name version) (name-and-version library-ref)))
(resolve-interface (transform-library-name name) #:version version)))
(define (exeq? x y) (if (list? y) (eq? x (cadr y)) (eq? x y)))
(if (or (not (list? im))) (error))
(let* ((op (car im))
	   (l (case op 
		((only except prefix rename) (flatten (cadr im)))
		((library) (load-library (cadr im)))
		(else (load-library im)
  (case op
	((library) (cons l (module-map (lambda (sym var) sym) l)))
	((only) (cons (car l) (lset-intersection exeq? (cdr l) (cddr im
	((except) (cons (car l) (lset-difference exeq? (cdr l) (cddr im
	((prefix) (let ((p (symbol-prefix-proc (caddr im
		(cons (car l) (map (lambda (x) 
	 (if (list? x) 
	 (cons (car x) (p (cadr x))) 
	 (cons x (p x
   (cdr 

Re: r6rs libraries, round three

2009-12-23 Thread Andy Wingo
On Sun 13 Dec 2009 04:24, Julian Graham jool...@gmail.com writes:

 Find attached updated versions of the patches that provide support for
 R6RS-compatible versions and renaming bindings on export (the two core
 modifications required to support the libraries implementation).
 They've been rebased against the current HEAD and some reasonably
 comprehensive documentation has been added.

Thanks for all. I wrapped your commit messages, detabbed the files, and
did some minor editing. Please look at the diffs relative to your
patches. But other than that, thanks very much! :-))

Andy
-- 
http://wingolog.org/




Re: r6rs libraries, round three

2009-12-23 Thread Neil Jerram
Julian Graham jool...@gmail.com writes:

 On a related note, I assume Emacs' `scheme-mode' has been adding
 unwanted tabs?  What should I do to correct this in my local
 environment?

(setq indent-tabs-mode nil)

 Neil




Re: r6rs libraries, round three

2009-12-12 Thread Julian Graham
Hi all,

Find attached updated versions of the patches that provide support for
R6RS-compatible versions and renaming bindings on export (the two core
modifications required to support the libraries implementation).
They've been rebased against the current HEAD and some reasonably
comprehensive documentation has been added.

Questions?  Comments?


Regards,
Julian
From bb83bbd13263aca6a1e8b246fd68ce96f5dcdb43 Mon Sep 17 00:00:00 2001
From: Julian Graham julian.gra...@aya.yale.edu
Date: Thu, 10 Dec 2009 00:29:11 -0500
Subject: [PATCH 1/2] Support for renaming bindings on module export.

* module/ice-9/boot-9.scm (module-export!, module-replace!, module-re-export!):
Allow members of export list to be pairs, mapping internal names to external ones.

* doc/ref/api-modules.texi (Creating Guile Modules): Update documentation for `#:export', `#:export-syntax', `#:replace', `#:re-export', `#:re-export-syntax', `export', and `re-export' to reflect new format for arguments.
---
 doc/ref/api-modules.texi |   50 +
 module/ice-9/boot-9.scm  |   24 +
 2 files changed, 43 insertions(+), 31 deletions(-)

diff --git a/doc/ref/api-modules.texi b/doc/ref/api-modules.texi
index 1c9ab23..65a3564 100644
--- a/doc/ref/api-modules.texi
+++ b/doc/ref/api-modules.texi
@@ -421,40 +421,42 @@ the module is used.
 
 @item #:export @var{list}
 @cindex export
-Export all identifiers in @var{list} which must be a list of symbols.
-This is equivalent to @code{(export @var{list})} in the module body.
+Export all identifiers in @var{list} which must be a list of symbols
+or pairs of symbols. This is equivalent to @code{(export @var{list})} 
+in the module body.
 
 @item #:re-export @var{list}
 @cindex re-export
 Re-export all identifiers in @var{list} which must be a list of
-symbols.  The symbols in @var{list} must be imported by the current
-module from other modules.  This is equivalent to @code{re-export}
-below.
+symbols or pairs of symbols.  The symbols in @var{list} must be 
+imported by the current module from other modules.  This is equivalent
+to @code{re-export} below.
 
 @item #:export-syntax @var{list}
 @cindex export-syntax
-Export all identifiers in @var{list} which must be a list of symbols.
-The identifiers in @var{list} must refer to macros (@pxref{Macros})
-defined in the current module.  This is equivalent to
-...@code{(export-syntax @var{list})} in the module body.
+Export all identifiers in @var{list} which must be a list of symbols
+or pairs of symbols.  The identifiers in @var{list} must refer to 
+macros (@pxref{Macros}) defined in the current module.  This is 
+equivalent to @code{(export-syntax @var{list})} in the module body.
 
 @item #:re-export-syntax @var{list}
 @cindex re-export-syntax
 Re-export all identifiers in @var{list} which must be a list of
-symbols.  The symbols in @var{list} must refer to macros imported by
-the current module from other modules.  This is equivalent to
-...@code{(re-export-syntax @var{list})} in the module body. 
+symbols or pairs of symbols.  The symbols in @var{list} must refer to
+macros imported by the current module from other modules.  This is 
+equivalent to @code{(re-export-syntax @var{list})} in the module body. 
 
 @item #:replace @var{list}
 @cindex replace
 @cindex replacing binding
 @cindex overriding binding
 @cindex duplicate binding
-Export all identifiers in @var{list} (a list of symbols) and mark them
-as @dfn{replacing bindings}.  In the module user's name space, this
-will have the effect of replacing any binding with the same name that
-is not also ``replacing''.  Normally a replacement results in an
-``override'' warning message, @code{#:replace} avoids that.
+Export all identifiers in @var{list} (a list of symbols or pairs of
+symbols) and mark them as @dfn{replacing bindings}.  In the module 
+user's name space, this will have the effect of replacing any binding 
+with the same name that is not also ``replacing''.  Normally a 
+replacement results in an ``override'' warning message, 
+...@code{#:replace} avoids that.
 
 This is useful for modules that export bindings that have the same
 name as core bindings.  @code{#:replace}, in a sense, lets Guile know
@@ -562,8 +564,11 @@ do not know anything about dangerous procedures.
 @c end
 
 @deffn syntax export variable @dots{}
-Add all @var{variable}s (which must be symbols) to the list of exported
-bindings of the current module.
+Add all @var{variable}s (which must be symbols or pairs of symbols) to 
+the list of exported bindings of the current module.  If @var{variable}
+is a pair, its @code{car} gives the name of the variable as seen by the
+current module and its @code{cdr} specifies a name for the binding in
+the current module's public interface.
 @end deffn
 
 @c begin (scm-doc-string boot-9.scm define-public)
@@ -573,9 +578,10 @@ Equivalent to @code{(begin (define foo ...) (export foo))}.
 @c end
 
 @deffn syntax re-export variable @dots{}

Re: r6rs libraries, round three

2009-11-17 Thread Julian Graham
Hi Andy,

 Note that quasisyntax is now merged. You can do things without
 quasisyntax using with-syntax.

Of course -- our version of quasisyntax is implemented in terms of
with-syntax!  I was just being lazy.


 Your code is remarkably short. That is my initial impression, positive
 :-) But I need to get to writing the NEWS now for today's release. I'll
 take a look at these within the next week hopefully. Please poke if you
 don't get another response in the next week.

I probably should have said rough prototype instead of working
prototype -- the actual macro that transforms library definitions
into module definitions is kind of gross and uses datum-syntax a fair
amount where it probably doesn't need to / shouldn't.  I'm no syncase
wizard.  But I'm pretty sure it works for conventional libraries that
import and export macros and regular bindings.  (What I worry about
are some of the hairier use cases of the whole phased import
mechanism -- like a binding that's imported at `meta' level 2 or
higher sharing a name with definition imported for use at runtime.)

What I'm mostly interested in is whether you guys think the version
and export patches are worth merging in some form or another -- my
assumption has been these are features we actually want for Guile's
module system.


Thanks,
Julian




Re: r6rs libraries, round three

2009-11-17 Thread Andreas Rottmann
Andy Wingo wi...@pobox.com writes:

 Hi Julian!

 On Sun 01 Nov 2009 20:26, Julian Graham jool...@gmail.com writes:

 Find attached a working prototype of R6RS library support

 I think I missed this one, it was threaded above the end of guile-devel
 that I read :-) Sorry about that.

 Note that quasisyntax is now merged. You can do things without
 quasisyntax using with-syntax. I haven't actually had the pleasure yet
 of using quasisyntax :P

Speaking of psyntax: have you had a look at my tail patterns patch[0]
yet? If it is deemed, ok, I can add ChangeLog and NEWS entries, and
update the documentation (anything else?).

[0] http://article.gmane.org/gmane.lisp.guile.devel/9605/match=tail+pattern

Regards, Rotty
-- 
Andreas Rottmann -- http://rotty.yi.org/




Re: r6rs libraries, round three

2009-11-17 Thread Andreas Rottmann
Julian Graham jool...@gmail.com writes:

 I probably should have said rough prototype instead of working
 prototype -- the actual macro that transforms library definitions
 into module definitions is kind of gross and uses datum-syntax a fair
 amount where it probably doesn't need to / shouldn't.  I'm no syncase
 wizard.  But I'm pretty sure it works for conventional libraries that
 import and export macros and regular bindings.  (What I worry about
 are some of the hairier use cases of the whole phased import
 mechanism -- like a binding that's imported at `meta' level 2 or
 higher sharing a name with definition imported for use at runtime.)

IIRC, R6RS doesn't /require/ that implementations are able to
differentiate bindings from different phases -- e.g. Ikarus essentially
ignores phase specifications (implicit phasing -- there were some
discussions about that on ikarus-users, which I can't find ATM, but [0]
should sum the issue up nicely).

[0] http://www.phyast.pitt.edu/~micheles/scheme/scheme21.html

 What I'm mostly interested in is whether you guys think the version
 and export patches are worth merging in some form or another -- my
 assumption has been these are features we actually want for Guile's
 module system.

Are you aware of SRFI-103? It got recently revised to leave out
versions; not supporting them is an option, I guess. Quoting from R6RS:

,
| When more than one library is identified by a library reference, the
| choice of libraries is determined in some implementation-dependent
| manner.
| 
| To avoid problems such as incompatible types and replicated state,
| implementations should prohibit the two libraries whose library names
| consist of the same sequence of identifiers but whose versions do not
| match to co-exist in the same program.
`

This makes me wonder if versions can be used (or rather be relied on)
sensibly in portable libraries at all...

Regards, Rotty
-- 
Andreas Rottmann -- http://rotty.yi.org/




Re: r6rs libraries, round three

2009-11-17 Thread Julian Graham
Hi Andreas,


 IIRC, R6RS doesn't /require/ that implementations are able to
 differentiate bindings from different phases -- e.g. Ikarus essentially
 ignores phase specifications (implicit phasing -- there were some
 discussions about that on ikarus-users, which I can't find ATM, but [0]
 should sum the issue up nicely).

You're right, it doesn't -- at least, it's not required that an
implementation prevent you from referencing an identifier at a phase
other than the one it was imported for.  I was reading that part of
the spec in terms of non-macro definitions, but, come to think of it,
it's got to apply to macros as well.  So importing everything at once
sounds like it'll work just fine.


 Are you aware of SRFI-103? It got recently revised to leave out
 versions; not supporting them is an option, I guess. Quoting from R6RS:

I was tracking SRFI-103 for a while back when it was (I think)
SRFI-100.  I'm interested to see how it pans out, but I'm not sure I
agree with its rationale -- it seems mostly useful for implementations
that don't currently have their own library search mechanism.  The bit
about distributing and using library files in a portable way seems a
bit hand-wavy to me.


 This makes me wonder if versions can be used (or rather be relied on)
 sensibly in portable libraries at all...

Yes, it's a bit thorny.  We discussed the limitations in a thread [1]
a while back.  The implementation I did reflects the outcome of that
thread, which was that the version of a library that gets loaded is a
function of the import statements, the available libraries, and the
set of already-loaded libraries -- which means that it's not a fully
predictable process from the point of view of library authors, but
that in practice, collisions aren't likely for a variety of reasons.


Regards,
Julian

[1] - http://www.mail-archive.com/guile-devel@gnu.org/msg03673.html




Re: r6rs libraries, round three

2009-11-16 Thread Julian Graham
 As I said earlier, I'm happy to provide full documentation for all of
 this code if the consensus is that I'm on the right track.


Any feeling either way on those patches?  I'm happy to create a remote
tracking branch if that'd make it easier for people to review.




Re: r6rs libraries, round three

2009-11-01 Thread Julian Graham
Hi all,

Find attached a working prototype of R6RS library support, in the form
of a Guile module called `(r6rs-libraries)'.  The module depends on
the two attached patches, which add, respectively, support for the
`#:version' keyword [1] and support for renaming bindings on export
[2].  It works by transforming the R6RS `library' form into Guile's
native `define-module' form.  Because it's implemented as a macro,
it's only required at expansion time -- the resulting compiled module
has no dependencies on anything besides other Guile modules.

Andreas Rottmann's quasisyntax implementation is included as part of
`(r6rs-libraries)' since it's not yet in master and I was finding it
difficult to model some things without `unsyntax-splicing'.

Also attached are a minimal set of R6RS libraries (as
`r6rs-libs.tar.gz') needed to bootstrap the examples from chapter 7 of
the R6RS spec (attached as `r6rs-examples.tar.gz').  If you place the
r6rs-libraries.scm and the contents of these tarballs somwhere in your
`%load-path', you can run the balloon party example as follows:

  scheme@(guile-user) (use-modules (r6rs-libraries))
  scheme@(guile-user) (use-modules (main))
  Boom 108
  Boom 24

...and the let-div example as follows:

  scheme@(guile-user) (use-modules (r6rs-libraries))
  scheme@(guile-user) (use-modules (let-div))
  scheme@(guile-user) (let-div 5 2 (q r) (display q: ) (display q)
(display  r: ) (display r) (newline))
  q: 2 r: 1

There are certainly some aspects of this implementation that require
review -- in particular, I've added infrastructure to distinguish
between imports targeted for different phases (i.e., `run', `expand'
... (meta n)), but at the moment, all imports are currently included
via #:use-module, which means they're visible at every point from
expansion to runtime.  R6RS seems to explicitly allow this, though,
and, quite frankly, it's much easier to implement.

As I said earlier, I'm happy to provide full documentation for all of
this code if the consensus is that I'm on the right track.


Regards,
Julian

[1] - http://www.mail-archive.com/guile-devel@gnu.org/msg04506.html
[2] - http://www.mail-archive.com/guile-devel@gnu.org/msg04660.html
From adcbc77ca4ca68f26da05a204154d826a832a7b7 Mon Sep 17 00:00:00 2001
From: Julian Graham julian.gra...@aya.yale.edu
Date: Sun, 25 Oct 2009 13:17:40 -0400
Subject: [PATCH] Complete support for version information in Guile's `module' form.

* module/ice-9/boot-9.scm (try-load-module, try-module-autoload): Check for version argument and use `find-versioned-module' if present.
* module/ice-9/boot-9.scm (find-versioned-module, version-matches?, module-version, set-module-version!, version-matches?): New functions.
* module/ice-9/boot-9.scm (module-type, make-module, resolve-module, try-load-module, process-define-module, make-autoload-interface, compile-interface-spec): Add awareness and checking of version information.
---
 module/ice-9/boot-9.scm |  149 ++-
 1 files changed, 133 insertions(+), 16 deletions(-)

diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm
index 5852477..3d92fad 100644
--- a/module/ice-9/boot-9.scm
+++ b/module/ice-9/boot-9.scm
@@ -1333,7 +1333,7 @@
   (make-record-type 'module
 		'(obarray uses binder eval-closure transformer name kind
 		  duplicates-handlers import-obarray
-		  observers weak-observers)
+		  observers weak-observers version)
 		%print-module))
 
 ;; make-module opt size uses binder
@@ -1374,7 +1374,7 @@
   #f #f #f
 	  (make-hash-table %default-import-size)
 	  '()
-	  (make-weak-key-hash-table 31
+	  (make-weak-key-hash-table 31) #f)))
 
 	  ;; We can't pass this as an argument to module-constructor,
 	  ;; because we need it to close over a pointer to the module
@@ -1396,6 +1396,8 @@
 
 (define module-transformer (record-accessor module-type 'transformer))
 (define set-module-transformer! (record-modifier module-type 'transformer))
+(define module-version (record-accessor module-type 'version))
+(define set-module-version! (record-modifier module-type 'version))
 ;; (define module-name (record-accessor module-type 'name)) wait until mods are booted
 (define set-module-name! (record-modifier module-type 'name))
 (define module-kind (record-accessor module-type 'kind))
@@ -2001,6 +2003,7 @@
 	(eq? interface module))
 	(let ((interface (make-module 31)))
 	  (set-module-name! interface (module-name module))
+	  (set-module-version! interface (module-version module))
 	  (set-module-kind! interface 'interface)
 	  (set-module-public-interface! module interface
   (if (and (not (memq the-scm-module (module-uses module)))
@@ -2008,6 +2011,101 @@
   ;; Import the default set of bindings (from the SCM module) in MODULE.
   (module-use! module the-scm-module)))
 
+(define (version-matches? version-ref target)
+  (define (any prec lst)
+(and (not (null? lst)) (or 

Re: r6rs libraries, round three

2009-10-25 Thread Julian Graham
Hi Andy,

 It should work now, though with hacks -- if you manipulate the
 module-public-interface directly. But perhaps some more baked in support
 would be useful.

Oh, certainly -- as I've learned over these many months, you can do
some very interesting things by working with the lower-level module
API.  And indeed, that was how I did things in my initial
implementation back in March.  But...


 Can you explain a use case a bit more? I think having trouble grasping
 why you would want to do this :)

I'm trying to write a macro to convert `library' forms into
`define-module' forms.  All of the contortions you can put your
imported symbols through in R6RS can be flattened into a form that
maps quite neatly onto define-module's #:select, but #:export and
#:reexport aren't as flexible.  Specifically, the use case is
implementing the

  (rename (identifier1 identifier2) ...)

form for R6RS library export-specs.  Like you said, you can manipulate
the public interface directly -- I could, say, insert the code to do
this as part of transforming the library body -- but it would be nice
if I could leave the management of the interface entirely up to
`define-module'.


Regards,
Julian




Re: r6rs libraries, round three

2009-10-24 Thread Julian Graham
Hi all,

Besides version, another thing that would be very useful to have
native Guile support for is being able to export bindings with names
other than the ones given to them within the module -- that is, to be
able to rename variables exported as part of the module's public
interface in `define-module', similar to what the `#:select' keyword
allows you to do for imported bindings.

In fact, it could even work the same the way: a given element in the
list passed with the `#:export' keyword could be either a symbol or a
pair in which the car is the module-local name and the cdr is the name
to use in the module's public interface.

What do people think?


Regards,
Julian




Re: r6rs libraries, round three

2009-09-30 Thread Julian Graham
Hi Guilers,

Okay, after poking around in the manual and the code, it looks like
`load-module' does what I need.

Find attached two patches that, combined, add full support for
R6RS-style version information to Guile's module system.  I've done a
bit of testing and believe that this code does the Right Thing in a
variety of situations -- e.g., it always attempts to select the
highest version number but can recover from situations in which
paths corresponding to higher-numbered versions don't contain actual
module implementations.

Questions, comments?  If it seems like this code is on the right
track, I'll add documentation to the appropriate locations.
boot-9.scm is getting a little bit crowded, though -- I don't suppose
it makes sense to move some of the module handling code to an
auxiliary file?


Regards,
Julian
From a1d49c00cd6cc144bf526481e5ba7da6aefa0822 Mon Sep 17 00:00:00 2001
From: Julian Graham julian.gra...@aya.yale.edu
Date: Sat, 26 Sep 2009 14:52:56 -0400
Subject: [PATCH] Initial support for version information in Guile's `module' form.

* module/ice-9/boot-9.scm (module-version, set-module-version!, version-matches?):
New functions.
* module/ice-9/boot-9.scm (module-type, make-module, resolve-module, try-load-module, process-define-module, make-autoload-interface, compile-interface-spec):
Add awareness and checking of version information.
---
 module/ice-9/boot-9.scm |   42 ++
 1 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm
index a1537d1..b49f799 100644
--- a/module/ice-9/boot-9.scm
+++ b/module/ice-9/boot-9.scm
@@ -1332,8 +1332,8 @@
 (define module-type
   (make-record-type 'module
 		'(obarray uses binder eval-closure transformer name kind
-		  duplicates-handlers import-obarray
-		  observers weak-observers)
+		  duplicates-handlers import-obarray observers 
+		  weak-observers version)
 		%print-module))
 
 ;; make-module opt size uses binder
@@ -1374,13 +1374,12 @@
   #f #f #f
 	  (make-hash-table %default-import-size)
 	  '()
-	  (make-weak-key-hash-table 31
+	  (make-weak-key-hash-table 31) #f)))
 
 	  ;; We can't pass this as an argument to module-constructor,
 	  ;; because we need it to close over a pointer to the module
 	  ;; itself.
 	  (set-module-eval-closure! module (standard-eval-closure module))
-
 	  module
 
 (define module-constructor (record-constructor module-type))
@@ -1396,6 +1395,8 @@
 
 (define module-transformer (record-accessor module-type 'transformer))
 (define set-module-transformer! (record-modifier module-type 'transformer))
+(define module-version (record-accessor module-type 'version))
+(define set-module-version! (record-modifier module-type 'version))
 ;; (define module-name (record-accessor module-type 'name)) wait until mods are booted
 (define set-module-name! (record-modifier module-type 'name))
 (define module-kind (record-accessor module-type 'kind))
@@ -2008,24 +2009,32 @@
   ;; Import the default set of bindings (from the SCM module) in MODULE.
   (module-use! module the-scm-module)))
 
+;; Temporary kludge before implementing full version matching.
+(define version-matches? equal?)
+
 ;; NOTE: This binding is used in libguile/modules.c.
 ;;
 (define resolve-module
   (let ((the-root-module the-root-module))
-(lambda (name . maybe-autoload)
+(lambda (name . args)  
   (if (equal? name '(guile))
   the-root-module
   (let ((full-name (append '(%app modules) name)))
-(let ((already (nested-ref the-root-module full-name))
-  (autoload (or (null? maybe-autoload) (car maybe-autoload
+(let* ((already (nested-ref the-root-module full-name))
+		   (numargs (length args))
+		   (autoload (or (= numargs 0) (car args)))
+		   (version (and ( numargs 1) (cadr args
   (cond
((and already (module? already)
  (or (not autoload) (module-public-interface already)))
 ;; A hit, a palpable hit.
+		(and version 
+		 (not (version-matches? version (module-version already)))
+		 (error incompatible module version already loaded name))
 already)
(autoload
 ;; Try to autoload the module, and recurse.
-(try-load-module name)
+(try-load-module name version)
 (resolve-module name #f))
(else
 ;; A module is not bound (but maybe something else is),
@@ -2071,7 +2080,7 @@
 
 ;; (define-special-value '(%app modules new-ws) (lambda () (make-scm-module)))
 
-(define (try-load-module name)
+(define (try-load-module name version)
   (try-module-autoload name))
 
 (define (purify-module! module)
@@ -2132,7 +2141,8 @@
 		  (let ((prefix (get-keyword-arg args #:prefix #f)))
 			(and prefix