Wrote a patch to add SRFI-97 (
https://srfi.schemers.org/srfi-97/srfi-97.html ) support, which allows
SRFIs to be imported as

    (use-modules ((srfi :XX)))
    (import (srfi :XX))

in addition to

    (use-modules ((srfi srfi-XX)))
    (import (srfi srfi-XX))

The SRFI is meant as a way to provide a portable way to import SRFI libraries.

There is one problem, though. If the scheme reader option keywords is
set to 'prefix, SRFI libraries cannot be imported in SRFI-97 style
till it is turned off or to 'postfix. This happens because SRFI-97
isn't implemented as a macro. Instead it is implemented inside the
resolve-module procedure.

Patch includes tests as well as documentation (including the note that
setting the keywords option to 'prefix prevents it from working).


Freja Nordsiek
From 4c521cbd3e805ebb93e521ebea7234d797152a53 Mon Sep 17 00:00:00 2001
From: Freja Nordsiek <[email protected]>
Date: Tue, 28 Mar 2017 01:56:39 +0200
Subject: [PATCH] Added SRFI-97.

* module/ice-9/boot-9.scm (resolve-module): Added SRFI-97 library name
  aliasing.
* module/ice-9/boot-9.scm (%cond-expand-features): Added SRFI-97
* test-suite/tests/srfi-97.test: Added tests for SRFI-97
* test-suite/Makefile: Included new tests.
* doc/ref/srfi-modules.texi: Added SRFI-97 documentation
* doc/ref/api-modules.texi: Added SRFI-97 information to module import
  documentation
* doc/ref/api-data.texi: Added note that keywords 'prefix and SRFI-97 do not
  work together.
* doc/ref/api-evaluation.texi: Added note that keywords 'prefix and SRFI-97 do
  not work together.
---
 doc/ref/api-data.texi         |  4 +++-
 doc/ref/api-evaluation.texi   |  4 +++-
 doc/ref/api-modules.texi      |  8 +++++++-
 doc/ref/srfi-modules.texi     | 37 ++++++++++++++++++++++++++++++++++---
 module/ice-9/boot-9.scm       | 21 +++++++++++++++++++--
 test-suite/Makefile.am        |  1 +
 test-suite/tests/srfi-97.test | 28 ++++++++++++++++++++++++++++
 7 files changed, 95 insertions(+), 8 deletions(-)
 create mode 100644 test-suite/tests/srfi-97.test

diff --git a/doc/ref/api-data.texi b/doc/ref/api-data.texi
index 214c6e2..33b11b0 100644
--- a/doc/ref/api-data.texi
+++ b/doc/ref/api-data.texi
@@ -5410,7 +5410,9 @@ keywords are self-quoting objects.
 
 If the @code{keywords} read option is set to @code{'prefix}, Guile also
 recognizes the alternative read syntax @code{:NAME}.  Otherwise, tokens
-of the form @code{:NAME} are read as symbols, as required by R5RS.
+of the form @code{:NAME} are read as symbols, as required by R5RS.  Note
+that this option prevents SRFI-97 style SRFI library references from
+working (@pxref{SRFI-97}).
 
 @cindex SRFI-88 keyword syntax
 
diff --git a/doc/ref/api-evaluation.texi b/doc/ref/api-evaluation.texi
index 202ebdc..f397e4b 100644
--- a/doc/ref/api-evaluation.texi
+++ b/doc/ref/api-evaluation.texi
@@ -355,7 +355,9 @@ Similarly, the @code{#!curly-infix} reader directive sets the
 @code{curly-infix} read option on the port, and
 @code{#!curly-infix-and-bracket-lists} sets @code{curly-infix} and
 unsets @code{square-brackets} on the port (@pxref{SRFI-105}).  There is
-currently no other way to access or set the per-port read options.
+currently no other way to access or set the per-port read options.  Note
+that setting @code{keywords} to @code{'prefix} prevents SRFI-97 style SRFI
+library references from working (@pxref{SRFI-97}).
 
 The boolean options may be toggled with @code{read-enable} and
 @code{read-disable}. The non-boolean @code{keywords} option must be set
diff --git a/doc/ref/api-modules.texi b/doc/ref/api-modules.texi
index 8f18b1e..aea75a8 100644
--- a/doc/ref/api-modules.texi
+++ b/doc/ref/api-modules.texi
@@ -174,6 +174,10 @@ Note that just as with a @code{use-modules} statement, any module that
 has not yet been loaded will be loaded when referenced by a @code{@@} or
 @code{@@@@} form.
 
+Note that SRFI libraries can be referred to as @code{(srfi srfi-@var{number})}
+or @code{(srfi :@var{number})}, where @var{number} is the number of the SRFI
+needed.  @xref{SRFI-97}, for documentation of the latter form.
+
 You can also use the @code{@@} and @code{@@@@} syntaxes as the target
 of a @code{set!} when the binding refers to a variable.
 
@@ -846,7 +850,9 @@ been defined and @var{autoload} is true, try to auto-load it.  When it
 can't be found that way either, create an empty module if @var{ensure}
 is true, otherwise return @code{#f}.  If @var{version} is true, ensure
 that the resulting module is compatible with the given version reference
-(@pxref{R6RS Version References}).  The name is a list of symbols.
+(@pxref{R6RS Version References}).  The name is a list of symbols.  Note
+that this procedure allows the usage of SRFI-97 style SRFI references
+(@pxref{SRFI-97}).
 @end deffn
 
 @deffn {Scheme Procedure} resolve-interface name [#:select=#f] @
diff --git a/doc/ref/srfi-modules.texi b/doc/ref/srfi-modules.texi
index f712944..16e9f65 100644
--- a/doc/ref/srfi-modules.texi
+++ b/doc/ref/srfi-modules.texi
@@ -60,6 +60,7 @@ get the relevant SRFI documents from the SRFI home page
 * SRFI-69::                     Basic hash tables.
 * SRFI-87::                     => in case clauses.
 * SRFI-88::                     Keyword objects.
+* SRFI-97::                     Standardized way to reference SRFI libraries.
 * SRFI-98::                     Accessing environment variables.
 * SRFI-105::                    Curly-infix expressions.
 * SRFI-111::                    Boxes.
@@ -81,8 +82,11 @@ There are several reasons for this inconsistency.  First, the feature
 checking syntactic form @code{cond-expand} (@pxref{SRFI-0}) must be
 available immediately, because it must be there when the user wants to
 check for the Scheme implementation, that is, before she can know that
-it is safe to use @code{use-modules} to load SRFI support modules.  The
-second reason is that some features defined in SRFIs had been
+it is safe to use @code{use-modules} to load SRFI support modules.
+Second, the feature to reference SRFI libraries using the syntax
+@code{(srfi :@var{number})} needs to be immediately available to
+facilitate importing SRFI modules using it (@pxref{SRFI-97}).  The
+third reason is that some features defined in SRFIs had been
 implemented in Guile before the developers started to add SRFI
 implementations as modules (for example SRFI-13 (@pxref{SRFI-13})).  In
 the future, it is possible that SRFIs in the core library might be
@@ -94,7 +98,8 @@ you want, you can do that already.  We have included the module
 but ensures that you can write future-safe code.
 
 Generally, support for a specific SRFI is made available by using
-modules named @code{(srfi srfi-@var{number})}, where @var{number} is the
+modules named @code{(srfi srfi-@var{number})} or
+@code{(srfi :@var{number})}, where @var{number} is the
 number of the SRFI needed.  Another possibility is to use the command
 line option @code{--use-srfi}, which will load the necessary modules
 automatically (@pxref{Invoking Guile}).
@@ -165,6 +170,7 @@ srfi-55
 srfi-61
 srfi-62
 srfi-87
+srfi-97
 srfi-105
 @end example
 
@@ -5457,6 +5463,31 @@ Return the keyword object whose name is @var{str}.
 @end example
 @end deffn
 
+@node SRFI-97
+@subsection SRFI-97 - Alternative way to import SRFI libraries
+@cindex SRFI-97
+
+This SRFI lets a Scheme program import SRFI libraries in a portable fashion
+across implementations by referencing them like @code{(srfi :@var{number})},
+where @var{number} is the number of the SRFI needed.  To import SRFI-1
+this way,
+
+@example
+(use-modules ((srfi :1)))
+@end example
+
+or
+
+@example
+(import (srfi :1))
+@end example
+
+This module is loaded by default.
+
+Note that this syntax for referring to SRFI libraries does not work if the
+@code{keywords} read option is set to @code{'prefix}
+(@pxref{Keyword Read Syntax}).
+
 @node SRFI-98
 @subsection SRFI-98 Accessing environment variables.
 @cindex SRFI-98
diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm
index 2777672..df5ec26 100644
--- a/module/ice-9/boot-9.scm
+++ b/module/ice-9/boot-9.scm
@@ -2696,8 +2696,24 @@ deterministic."
     ;; Define the-root-module as '(guile).
     (module-define-submodule! root 'guile the-root-module)
 
-    (lambda* (name #:optional (autoload #t) (version #f) #:key (ensure #t))
-      (let ((already (nested-ref-module root name)))
+    (lambda* (name-unproc #:optional (autoload #t) (version #f) #:key (ensure #t))
+      ;; Implement SRFI-97 by first converting module names of the form
+      ;; ('srfi ':XXXXX ...) to ('srfi 'srfi-XXXXX) where X are base 10 digits.
+      (let* ((name (if (and (list? name-unproc) (not (null? name-unproc))
+                            (not (null? (cdr name-unproc)))
+                            (equal? 'srfi (car name-unproc))
+                            (let ((s (symbol->string (cadr name-unproc)))
+                                  (digits (string->char-set "0123456789")))
+                              (and (string-prefix? ":" s)
+                                   (> (string-length s) 1)
+                                   (string-every (lambda (c) (char-set-contains? digits c))
+                                                 (substring s 1)))))
+                       (list 'srfi
+                             (string->symbol (string-append
+                                              "srfi-"
+                                              (substring (symbol->string (cadr name-unproc)) 1))))
+                       name-unproc))
+             (already (nested-ref-module root name)))
         (cond
          ((and already
                (or (not autoload) (module-public-interface already)))
@@ -3895,6 +3911,7 @@ when none is available, reading FILE-NAME with READER."
     srfi-61  ;; general cond clause
     srfi-62  ;; s-expression comments
     srfi-87  ;; => in case clauses
+    srfi-97  ;; allow SRFI library references to take the form (srfi :XXXX)
     srfi-105 ;; curly infix expressions
     ))
 
diff --git a/test-suite/Makefile.am b/test-suite/Makefile.am
index 3ce9070..793af52 100644
--- a/test-suite/Makefile.am
+++ b/test-suite/Makefile.am
@@ -156,6 +156,7 @@ SCM_TESTS = tests/00-initial-env.test		\
 	    tests/srfi-67.test			\
 	    tests/srfi-69.test			\
 	    tests/srfi-88.test			\
+	    tests/srfi-97.test			\
 	    tests/srfi-98.test			\
 	    tests/srfi-105.test			\
 	    tests/srfi-111.test			\
diff --git a/test-suite/tests/srfi-97.test b/test-suite/tests/srfi-97.test
new file mode 100644
index 0000000..c9ccf00
--- /dev/null
+++ b/test-suite/tests/srfi-97.test
@@ -0,0 +1,28 @@
+;;;; srfi-97.test --- Test suite for importing SRFIs using (srfi :number)
+;;;;
+;;;; Copyright (C) 2017 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
+
+(define-module (test-srfi-97)
+  #:use-module (test-suite lib)
+  #:use-module (srfi srfi-1))
+
+(define (to-bool x) (if x #t #f))
+
+(with-test-prefix "SRFI-97"
+  (pass-if "in cond-expand" (to-bool (find (lambda (x) (eq? 'srfi-97 x)) %cond-expand-features)))
+  (pass-if "use-modules" (to-bool (and (use-modules ((srfi :19))) (current-time time-utc))))
+  (pass-if "import" (to-bool (and (import (srfi :60)) (bitwise-not 2)))))
-- 
2.9.3

Reply via email to